N个数,M个查询,每次查询L到R区间的第k小元素。可以用treap离线做..读取所有的查询,按左区间排序,由于数据保证不存在互相包涵的查询,所以相邻的两个区间要么相离,要么部分交叉。相离就依次删除上一次的元素,再一次插入本次的元素;交叉就删除上次不重叠的部分,然后把本次不重叠的部分插入。
#include <cstdio> #include <iostream> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; const int maxn=200000+1000; int ch[maxn][2],val[maxn],counts[maxn],r[maxn],size[maxn],tot,root; struct TREAP { void newnode(int &rt,int v) { rt=++tot; val[rt]=v; ch[rt][0]=ch[rt][1]=0; counts[rt]=size[rt]=1; r[rt]=rand(); } inline void pushup(int rt) { size[rt]=size[ch[rt][0]]+size[ch[rt][1]]+counts[rt]; } void rotate(int &x,int kind) { int y=ch[x][kind^1]; ch[x][kind^1]=ch[y][kind]; ch[y][kind]=x; pushup(x); pushup(y); x=y; } void insert(int &rt,int v) { if(rt==0) { newnode(rt,v); return ; } if(v==val[rt]) counts[rt]++; else { int kind=(v>val[rt]); insert(ch[rt][kind],v); if(r[ch[rt][kind]]<r[rt]) rotate(rt,kind^1); } pushup(rt); } int select(int rt,int k) { if(size[ch[rt][0]]>=k) return select(ch[rt][0],k); if(size[ch[rt][0]]+counts[rt]>=k) return val[rt]; return select(ch[rt][1],k-size[ch[rt][0]]-counts[rt]); } void remove(int &rt,int v) { if(val[rt]==v) { if(counts[rt]>1) counts[rt]--; else if(!ch[rt][0]&&!ch[rt][1]) {rt=0;return ;} else { int kind=r[ch[rt][0]]<r[ch[rt][1]]; rotate(rt,kind); remove(rt,v); } } else remove(ch[rt][v>val[rt]],v); pushup(rt); } void init() { ch[0][0]=ch[0][1]=0; size[0]=counts[0]=val[0]=0; tot=root=0; r[0]=(1LL<<31)-1; newnode(root,2000000001); } }treap; struct node { int l,r,k,ans; int id; }a[50500]; bool cmp1(node p,node q) { if (p.l==q.l) return p.r<q.r; return p.l<q.l; } bool cmp2(node p,node q) { return p.id<q.id; } int n,m,k; int num[maxn]; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { for (int i=1; i<=n; i++) scanf("%d",&num[i]); for (int i=0; i<m; i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k),a[i].id=i; sort(a,a+m,cmp1); treap.init(); int lastl=a[0].l,lastr=a[0].r; for (int i=lastl; i<=lastr; i++) treap.insert(root,num[i]); a[0].ans=treap.select(root,a[0].k); for (int i=1; i<m; i++) { if (a[i].l>lastr) { for (int j=lastl; j<=lastr; j++) treap.remove(root,num[j]); for (int j=a[i].l; j<=a[i].r; j++) treap.insert(root,num[j]); } else { for (int j=lastl; j<a[i].l; j++) treap.remove(root,num[j]); for (int j=lastr+1; j<=a[i].r; j++) treap.insert(root,num[j]); } a[i].ans=treap.select(root,a[i].k); lastl=a[i].l; lastr=a[i].r; } sort(a,a+m,cmp2); for (int i=0; i<m; i++) cout<<a[i].ans<<endl; } return 0; }