【Luogu】P3332K大数查询(树套树)
这题我费尽心思不用标记永久化终于卡过去了qwq
权值线段树下面套一个区间线段树。然后乱搞搞即可。
// luogu-judger-enable-o2 #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<cctype> #define maxn 100050 #define mid ((l+r)>>1) #define left (root<<1) #define right (root<<1|1) #define check(o) if(o==0) o=++segtot; using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long tree[maxn*200];int segtot; int segrt[maxn*200]; int segls[maxn*200]; int segrs[maxn*200]; int tag[maxn*200]; int rt[maxn*10]; int q[maxn]; int n,m,cnt,size; void pushdown(int &root,int m){ check(root); if(tag[root]==0) return; check(segls[root]); check(segrs[root]); int le=segls[root],ri=segrs[root]; tag[le]+=tag[root]; tag[ri]+=tag[root]; tree[le]+=tag[root]*(m-(m>>1)); tree[ri]+=tag[root]*(m>>1); tag[root]=0; } void segup(int from,int to,int l,int r,int &root){ check(root); if(from<=l&&to>=r){ tree[root]+=(r-l+1); tag[root]++; return; } pushdown(root,r-l+1); if(from<=mid){ check(segls[root]); segup(from,to,l,mid,segls[root]); } if(to>mid){ check(segrs[root]); segup(from,to,mid+1,r,segrs[root]); } tree[root]=tree[segls[root]]+tree[segrs[root]]; } long long segquery(int from,int to,int l,int r,int &root){ check(root); if(from<=l&&to>=r) return tree[root]; pushdown(root,r-l+1); long long ans=0; if(from<=mid){ check(segls[root]); ans+=segquery(from,to,l,mid,segls[root]); } if(to>mid){ check(segrs[root]); ans+=segquery(from,to,mid+1,r,segrs[root]); } return ans; } void add(int o,int from,int to,int l,int r,int p){ segup(from,to,1,n,segrt[o]); if(l==r) return; if(p<=mid) add(o<<1,from,to,l,mid,p); else add(o<<1|1,from,to,mid+1,r,p); } long long query(int o,int from,int to,long long l,long long r,long long e){ if(l==r) return l; long long ans=segquery(from,to,1,n,segrt[o<<1|1]); if(ans>=e) return query(o<<1|1,from,to,mid+1,r,e); else return query(o<<1,from,to,l,mid,e-ans); } struct Que{ long long opt,a,b,c; }que[maxn]; int main(){ n=read(),m=read(); for(int i=1;i<=m;++i){ que[i]=(Que){read(),read(),read(),read()}; if(que[i].opt==1) q[++cnt]=que[i].c; } sort(q+1,q+cnt+1); size=unique(q+1,q+cnt+1)-q-1; for(int i=1;i<=m;++i){ if(que[i].opt!=1) continue; que[i].c=lower_bound(q+1,q+size+1,que[i].c)-q; } for(int i=1;i<=m;++i){ long long opt=que[i].opt,a=que[i].a,b=que[i].b,c=que[i].c; if(opt==1) add(1,a,b,1,size,c); else printf("%lld\n",q[query(1,a,b,1,size,c)]); } return 0; }