落谷 P3834 可持久化線段樹 1(主席樹)(區間第k小)
阿新 • • 發佈:2018-12-11
設區間為l,r,用r版本減去l版本求出區間第k小,一個板子
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; struct node1 { int v; int po; }ed[500005]; struct node2 { int v; int vy; }ed2[500005]; int cmp(node1 a,node1 b) { return a.v<b.v; } int cnt; int root[500005]; int tval[500005]; struct Tree { int lson; int rson; int val; }tree[500005*30]; void insert(int &rt,int ort,int l,int r,int po,int val) { if(!rt)rt=++cnt; if(l==r) { tree[rt].val=tree[ort].val+val; return; } int mid=(l+r)/2; if(po<=mid) { tree[rt].rson=tree[ort].rson; insert(tree[rt].lson,tree[ort].lson,l,mid,po,val); }else { tree[rt].lson=tree[ort].lson; insert(tree[rt].rson,tree[ort].rson,mid+1,r,po,val); } tree[rt].val=tree[tree[rt].lson].val+tree[tree[rt].rson].val; } int query(int rt,int ort,int l,int r,int k) { if(!rt)return 0; int mid=(l+r)/2; if(l==r) { return l; } if(k<=tree[tree[rt].lson].val-tree[tree[ort].lson].val) { return query(tree[rt].lson,tree[ort].lson,l,mid,k); }else { k-=tree[tree[rt].lson].val-tree[tree[ort].lson].val; return query(tree[rt].rson,tree[ort].rson,mid+1,r,k); } } int main() { int n,m; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) { scanf("%d",&ed[i].v); ed[i].po=i; } sort(ed+1,ed+1+n,cmp); int tt=1; ed2[ed[1].po].v=1; ed2[ed[1].po].vy=ed[1].v; for(int i = 2;i <= n;i++) { if(ed[i].v!=ed[i-1].v) { ed2[ed[i].po].v=++tt; ed2[ed[i].po].vy=ed[i].v; }else { ed2[ed[i].po].v=tt; ed2[ed[i].po].vy=ed[i].v; } } for(int i = 1;i <= n;i++) { insert(root[i],root[i-1],1,tt,ed2[i].v,1); tval[ed2[i].v]=ed2[i].vy; } for(int i = 1;i <= m;i++) { int a,b,kk; scanf("%d%d%d",&a,&b,&kk); int ty=query(root[b],root[a-1],1,tt,kk); printf("%d\n",tval[ty]); } return 0; }