bzoj3110: [Zjoi2013]K大数查询
Posted akcqhzdy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3110: [Zjoi2013]K大数查询相关的知识,希望对你有一定的参考价值。
整体二分加深理解~
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; int n; struct trnode { int l,r,lc,rc;LL c,lazy; }tr[110000];int trlen; void bt(int l,int r) { int now=++trlen; tr[now].l=l;tr[now].r=r; tr[now].lc=tr[now].rc=-1; tr[now].c=0;tr[now].lazy=0; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); } } void change(LL now,int l,int r,LL k) { if(tr[now].l==l&&tr[now].r==r) { tr[now].c+=(r-l+1)*k; tr[now].lazy+=k; return ; } int mid=(tr[now].l+tr[now].r)/2; int lc=tr[now].lc,rc=tr[now].rc; if(tr[now].lazy!=0) { tr[lc].c+=(tr[lc].r-tr[lc].l+1)*tr[now].lazy; tr[rc].c+=(tr[rc].r-tr[rc].l+1)*tr[now].lazy; tr[lc].lazy+=tr[now].lazy; tr[rc].lazy+=tr[now].lazy; tr[now].lazy=0; } if(r<=mid) change(lc,l,r,k); else if(mid+1<=l)change(rc,l,r,k); else change(lc,l,mid,k), change(rc,mid+1,r,k); tr[now].c=tr[lc].c+tr[rc].c; } LL getsum(int now,int l,int r) { if(l>r)return 0; if(tr[now].l==l&&tr[now].r==r)return tr[now].c; int mid=(tr[now].l+tr[now].r)/2; int lc=tr[now].lc,rc=tr[now].rc; if(tr[now].lazy!=0) { tr[lc].c+=(tr[lc].r-tr[lc].l+1)*tr[now].lazy; tr[rc].c+=(tr[rc].r-tr[rc].l+1)*tr[now].lazy; tr[lc].lazy+=tr[now].lazy; tr[rc].lazy+=tr[now].lazy; tr[now].lazy=0; } if(r<=mid) return getsum(lc,l,r); else if(mid+1<=l)return getsum(rc,l,r); else return getsum(lc,l,mid)+getsum(rc,mid+1,r); } //------------seg_tree---------------------- struct node { int t,x,y,k; }q[51000],lq[51000],rq[51000]; int as[51000]; void solve(LL l,LL r,int st,int ed) { if(st>ed)return ; if(l==r) { for(int i=st;i<=ed;i++) if(q[i].t>0)as[q[i].t]=l; return ; } LL mid=(l+r)/2,lt=0,rt=0; for(int i=st;i<=ed;i++) { if(q[i].t==0) { if(q[i].k<=mid)lq[++lt]=q[i]; else { change(1,q[i].x,q[i].y,1); rq[++rt]=q[i]; } } else { LL d=getsum(1,q[i].x,n)-getsum(1,q[i].y+1,n); if(d<q[i].k) { q[i].k-=d; lq[++lt]=q[i]; } else rq[++rt]=q[i]; } } for(int i=ed;i>=st;i--) if(q[i].t==0&&q[i].k>mid)change(1,q[i].x,q[i].y,-1); for(int i=1;i<=lt;i++)q[st+i-1]=lq[i]; for(int i=1;i<=rt;i++)q[st+lt+i-1]=rq[i]; solve(l,mid,st,st+lt-1); solve(mid+1,r,st+lt,ed); } char ss[10]; int main() { int Q,m=0,op; scanf("%d%d",&n,&Q); for(int i=1;i<=Q;i++) { scanf("%d%d%d%d",&op,&q[i].x,&q[i].y,&q[i].k); if(op==1)q[i].t=0; else q[i].t=++m; } trlen=0;bt(1,n); solve(0,(1LL<<33),1,Q); for(int i=1;i<=m;i++)printf("%d ",as[i]); return 0; }
以上是关于bzoj3110: [Zjoi2013]K大数查询的主要内容,如果未能解决你的问题,请参考以下文章