【树套树】bzoj3110 [Zjoi2013]K大数查询
题解很多,实现起来以外地简洁。内层的区间线段树上用了标记永久化。
#include<cstdio> using namespace std; #define N 50001 struct Node{int sumv,tag,lc,rc;}T[N*256]; int e; int n,m; void Update(int ql,int qr,int cur,int l,int r) { if(ql<=l&&r<=qr) ++T[cur].tag; else { int m=(l+r>>1); if(ql<=m) { if(!T[cur].lc) T[cur].lc=++e; Update(ql,qr,T[cur].lc,l,m); } if(m<qr) { if(!T[cur].rc) T[cur].rc=++e; Update(ql,qr,T[cur].rc,m+1,r); } } T[cur].sumv=T[T[cur].lc].sumv+T[T[cur].rc].sumv+T[cur].tag*(r-l+1); } int Query(int ql,int qr,int cur,int l,int r,int tag) { if(ql<=l&&r<=qr) return T[cur].sumv+(r-l+1)*tag; int m=(l+r>>1),res=0; if(ql<=m) res+=Query(ql,qr,T[cur].lc,l,m,tag+T[cur].tag); if(m<qr) res+=Query(ql,qr,T[cur].rc,m+1,r,tag+T[cur].tag); return res; } int root[N<<2]; void Update_2D(int ql,int qr,int p,int rt,int l,int r) { if(!root[rt]) root[rt]=++e; Update(ql,qr,root[rt],1,n); if(l==r) return; int m=(l+r>>1); if(p<=m) Update_2D(ql,qr,p,rt<<1,l,m); else Update_2D(ql,qr,p,rt<<1|1,m+1,r); } int Query_2D(int ql,int qr,int K,int rt,int l,int r) { if(l==r) return l; int m=(l+r>>1); int Src=Query(ql,qr,root[rt<<1|1],1,n,0); if(Src>=K) return Query_2D(ql,qr,K,rt<<1|1,m+1,r); else return Query_2D(ql,qr,K-Src,rt<<1,l,m); } int main() { int op,x,y,z; scanf("%d%d",&n,&m); for(;m;--m) { scanf("%d%d%d%d",&op,&x,&y,&z); if(op==1) Update_2D(x,y,z,1,1,n); else printf("%d\n",Query_2D(x,y,z,1,1,n)); } return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/