poj2104 求区间第k大 可持久化线段树
poj2104 求区间第k大 可持久化线段树
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=100100; const int INF=1e9+10; int n,m; int L,R,k; int a[maxn],b[maxn],bn; struct SegTree { int l,r; int ls,rs; int sum; void debug() { printf("l=%2d r=%2d ls=%2d rs=%2d sum=%2d\n",l,r,ls,rs,sum); } };SegTree T[maxn*64]; int root[maxn],tot; void push_up(int rt) { T[rt].sum=T[T[rt].ls].sum+T[T[rt].rs].sum; } int build(int l,int r) { int k=++tot; T[k].l=l;T[k].r=r; T[k].ls=-1;T[k].rs=-1; T[k].sum=0; if(l==r) return k; int m=(l+r)>>1; T[k].ls=build(l,m); T[k].rs=build(m+1,r); push_up(k); return k; } int update(int rt,int p,int c) { int k=++tot; T[k]=T[rt]; if(T[rt].l==T[rt].r){ T[k].sum+=c; return k; } int m=(T[rt].l+T[rt].r)>>1; if(p<=m) T[k].ls=update(T[rt].ls,p,c); else T[k].rs=update(T[rt].rs,p,c); push_up(k); return k; } int query(int s,int t,int k) { if(T[s].l==T[s].r) return T[s].l; int cnt=T[T[s].ls].sum-T[T[t].ls].sum; if(k<=cnt) return query(T[s].ls,T[t].ls,k); else return query(T[s].rs,T[t].rs,k-cnt); } int main() { freopen("in.txt","r",stdin); while(cin>>n>>m){ REP(i,1,n) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); bn=unique(b+1,b+n+1)-(b+1); REP(i,1,n) a[i]=lower_bound(b+1,b+bn+1,a[i])-b; tot=0; root[0]=build(1,bn); REP(i,1,n){ root[i]=update(root[i-1],a[i],1); } while(m--){ scanf("%d%d%d",&L,&R,&k); int kth=query(root[R],root[L-1],k); printf("%d\n",b[kth]); } } return 0; }
没有AC不了的题,只有不努力的ACMER!