bzoj 3110: [Zjoi2013]K大数查询 树状数组套线段树
2014-11-13 22:03
525 查看
3110: [Zjoi2013]K大数查询
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1384 Solved: 629
[Submit][Status]
Description
有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。
Input
第一行N,M接下来M行,每行形如1 a b c或2 a b c
Output
输出每个询问的结果Sample Input
2 51 1 2 1
1 1 2 2
2 1 1 2
2 1 1 1
2 1 2 3
Sample Output
12
1
HINT
【样例说明】第一个操作 后位置 1 的数只有 1 , 位置 2 的数也只有 1 。 第二个操作 后位置 1
的数有 1 、 2 ,位置 2 的数也有 1 、 2 。 第三次询问 位置 1 到位置 1 第 2 大的数 是
1 。 第四次询问 位置 1 到位置 1 第 1 大的数是 2 。 第五次询问 位置 1 到位置 2 第 3
大的数是 1 。
N,M<=50000,N,M<=50000
a<=b<=N
1操作中abs(c)<=N
2操作中abs(c)<=Maxlongint
这道题本来想用线段树套平衡树做,但是即便加了永久lazy标记,还是TLE了,后来改为树状数组套线段树,注意树状数组二分可优化为O(logn)
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define MAXN 101000 #define MAXT 28000000 #define lowbit(x) (x&(-x)) inline int nextInt() { register int x=0; register char ch; while (ch=(char)getchar(),ch<'0'||ch > '9'); do x=x*10+ch-'0'; while (ch=(char)getchar(),ch<='9' && ch>='0'); return x; } int n,m; struct sgt_node { int lch,rch; int t,lazy; }sgt[MAXT]; int topt=0; void Add_sgt(int &now,int l,int r,int x,int y) { if (!now) { now=++topt; sgt[now].t=sgt[now].lazy=0; } if (l==x && r==y) { sgt[now].t+=r-l+1; sgt[now].lazy++; return ; } int mid=(l+r)>>1; if (sgt[now].lazy) { if (!sgt[now].lch) sgt[now].lch=++topt; if (!sgt[now].rch) sgt[now].rch=++topt; sgt[sgt[now].lch].lazy+=sgt[now].lazy; sgt[sgt[now].rch].lazy+=sgt[now].lazy; sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+1); sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid); sgt[now].lazy=0; } if (y<=mid) { Add_sgt(sgt[now].lch,l,mid,x,y); }else if (mid<x) { Add_sgt(sgt[now].rch,mid+1,r,x,y); }else { Add_sgt(sgt[now].lch,l,mid,x,mid); Add_sgt(sgt[now].rch,mid+1,r,mid+1,y); } sgt[now].t=sgt[sgt[now].lch].t+sgt[sgt[now].rch].t; } int Qry_sgt(int &now,int l,int r,int x,int y) { if (!now || sgt[now].t==0)return 0; if (l==x && r==y) return sgt[now].t; int mid=(l+r)>>1; if (sgt[now].lazy) { if (!sgt[now].lch) sgt[now].lch=++topt; if (!sgt[now].rch) sgt[now].rch=++topt; sgt[sgt[now].lch].lazy+=sgt[now].lazy; sgt[sgt[now].rch].lazy+=sgt[now].lazy; sgt[sgt[now].lch].t+=sgt[now].lazy*(mid-l+1); sgt[sgt[now].rch].t+=sgt[now].lazy*(r-mid); sgt[now].lazy=0; } if (y<=mid) { return Qry_sgt(sgt[now].lch,l,mid,x,y); }else if (mid<x) { return Qry_sgt(sgt[now].rch,mid+1,r,x,y); }else { return Qry_sgt(sgt[now].lch,l,mid,x,mid) +Qry_sgt(sgt[now].rch,mid+1,r,mid+1,y); } } int tarr2[MAXN],tarr3[MAXN]; void Add_tarr2(int l,int r) { r++; int a=r; while (r<MAXN) { tarr2[r]--; tarr3[r]-=a; r+=lowbit(r); } a=l; while (l<MAXN) { tarr2[l]++; tarr3[l]+=a; l+=lowbit(l); } } //segma((n-i+1)*a[i]) //=(n+1)*segma(a[i]) - segma(i*a[i]) int Qry_tarr2(int l,int r) { int ret=0; int v1,v2; int now; v1=0; l--; now=r; v1=v2=0; while (now) { v1+=tarr2[now]; v2+=tarr3[now]; now-=lowbit(now); } ret+=v1*(r+1)-v2; now=l; v1=v2=0; while (now) { v1+=tarr2[now]; v2+=tarr3[now]; now-=lowbit(now); } ret-=v1*(l+1)-v2; return ret; } int tarr[MAXN]; void Add_tarr(int pos,int l,int r) { pos+=n+1; Add_tarr2(l,r); while (pos<MAXN) { Add_sgt(tarr[pos],0,n+1,l,r); pos+=lowbit(pos); } } /* int Qry_tarr(int rk,int ll,int rr) { int now=0,t; int i; int l,r,mid; rk=Qry_tarr2(ll,rr)-rk+1; l=-n-1;r=n+1; while (l+1<r) { t=0; mid=(l+r)>>1; now=mid+n+1; while (now) { t+=Qry_sgt(tarr[now],0,n+1,ll,rr); now-=lowbit(now); } if (t<rk) l=mid; else r=mid; } return r==-n ? 1 : r; }*/ int Qry_tarr(int rk,int ll,int rr) { int now=0,t; int i; int l,r,mid; rk=Qry_tarr2(ll,rr)-rk+1; for (i=20;i>=0;i--) { if (now+(1<<i)<MAXN && (t=Qry_sgt(tarr[now+(1<<i)],0,n+1,ll,rr))<rk) { rk-=t; now+=(1<<i); } } now=now+1-(n+1); return now; } int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); scanf("%d%d",&n,&m); int i; int opt,x,y,z; for (i=0;i<m;i++) { opt=nextInt(); x=nextInt(); y=nextInt(); z=nextInt(); //scanf("%d%d%d%d",&opt,&x,&y,&z); if (opt==1) { Add_tarr(z,x,y); }else { printf("%d\n",Qry_tarr(z,x,y)); } } }
树状数组+线段树
相关文章推荐
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
- 【整体二分+树状数组区间加区间和】BZOJ3110 [Zjoi2013]K大数查询
- 【BZOJ】3110 [Zjoi2013]K大数查询 整体二分+树状数组 || 树套树
- bzoj3110[Zjoi2013]K大数查询 主席树套线段树
- [BZOJ3110][ZJOI2013]K大数查询(线段树套线段树)
- 【线段树套线段树】[ZJOI 2013] bzoj3110 K大数查询
- 【BZOJ3110】K大数查询(ZJOI2013)-整体二分+线段树
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
- BZOJ 3110: [Zjoi2013]K大数查询|线段树套线段树
- BZOJ 3110 [Zjoi2013]K大数查询 (整体二分 + 树状数组或线段树处理区间合值)
- bzoj 3110: [Zjoi2013]K大数查询 线段树套线段树
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- BZOJ 3110 ZJOI 2013 K大数查询 树套树(权值线段树套区间线段树)
- BZOJ 3110([Zjoi2013]K大数查询-区间第k大[段修改,在线]-树状数组套函数式线段树)
- [BZOJ]3110: [Zjoi2013]K大数查询 整体二分+线段树
- 【bzoj3110】[Zjoi2013]K大数查询 权值线段树套区间线段树
- BZOJ 3110 ZJOI 2013 K大值查询 线段树套线段树
- bzoj3110 [Zjoi2013]K大数查询(整体二分+线段树)
- [BZOJ3110][Zjoi2013]K大数查询(主席树套线段树||整体二分 )
- 【bzoj3110】【ZJOI2013】【K大数查询】【权值线段树套位置线段树】