bzoj 1901: Zju2112 Dynamic Rankings 树状数组套线段树 cdq分治
2016-10-23 20:16
507 查看
题目
传送门树套树
一棵树状数组,每个节点上都是一棵权值线段树(不是可持久化线段树),线段树动态开节点。然后每次查询的时候二分答案就好了。
时间复杂度O(nlog^3)
勉强水过……
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int n,m,tot,root[10005],a[10005]; struct tree{int l,r,s;}t[2000005]; int lowbit(int x) { return x&(-x); } void insert(int &d,int l,int r,int x,int y) { if (!d) d=++tot; t[d].s+=y; if (l==r) return ; int mid=(l+r)/2; if (x<=mid) insert(t[d].l,l,mid,x,y); else insert(t[d].r,mid+1,r,x,y); } void ins(int x,int y) { while (x<=n) { insert(root[x],0,1000000000,y,1); x+=lowbit(x); } } void del(int x,int y) { while (x<=n) { insert(root[x],0,1000000000,y,-1); x+=lowbit(x); } } int find(int d,int l,int r,int x) { if (!d) return 0; if (l==r) return t[d].s; int mid=(l+r)/2; if (x<=mid) return find(t[d].l,l,mid,x); else return t[t[d].l].s+find(t[d].r,mid+1,r,x); } int solve(int x,int y,int z) { int p=0; x--; while (y) { p+=find(root[y],0,1000000000,z); y-=lowbit(y); } while (x) { p-=find(root[x],0,1000000000,z); x-=lowbit(x); } return p; } int query(int x,int y,int z) { int l=0,r=1000000000,ans=0; while (l<=r) { int mid=(l+r)/2; int w=solve(x,y,mid); if (w>=z) { r=mid-1; ans=mid; } else l=mid+1; } return ans; } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) root[i]=i; tot=n; for (int i=1;i<=n;i++) { scanf("%d",&a[i]); ins(i,a[i]); } for (int i=1;i<=m;i++) { char ch[2]; scanf("%s",ch); if (ch[0]=='Q') { int x,y,z; scanf("%d%d%d",&x,&y,&z); printf("%d\n",query(x,y,z)); }else { int x,y; scanf("%d%d",&x,&y); del(x,a[x]); ins(x,y); a[x]=y; } } return 0; }
cdq分治
今天学的一种新姿势。cdq分治说白了就是把所有操作都扔到一起,然后对整体进行二分,就是二分的是操作的区间,然后根据每个操作对其他操作的贡献继续二分。
在这题里面,我们可以把原序列看成是n个插入操作,每个修改操作可以看成是一个删除操作+一个插入操作。
接着我们在整体二分的同时二分一个答案mid,然后对二分到的操作进行处理:如果是插入或删除操作且该操作对应的值不大于mid就扔进树状数组里面,如果是查询操作就查找在对应区间内出现了多少个的数。同时每个查询操作记录之前已经找到了多少个数比mid要小。若当前比mid要小的数+之前找到的比mid要小的数>=x那么就把该查询操作扔到后面,否则扔到前面。
对于一个插入或删除操作,如果对应的值不大于mid就扔到前面因为可能对接着二分到的询问有影响,否则就扔到后面。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define N 10005 using namespace std; int n,m,tot,num,c ,ans ,a ; struct q{int l,r,x,op,tmp,cur,mark,pos,id;}q[N*10],tmp[N*10]; void ins(int x,int y) { while (x<=n) { c[x]+=y; x+=x&(-x); } } int query(int x) { int ans=0; while (x) { ans+=c[x]; x-=x&(-x); } return ans; } void cdq(int l,int r,int L,int R) { if (l>r) return; if (L==R) { for (int i=l;i<=r;i++) if (q[i].op==3) ans[q[i].id]=L; return; } int mid=(L+R)/2; for (int i=l;i<=r;i++) if (q[i].op==1&&q[i].x<=mid) ins(q[i].pos,1); else if (q[i].op==2&&q[i].x<=mid) ins(q[i].pos,-1); else if (q[i].op==3) q[i].tmp=query(q[i].r)-query(q[i].l-1); for (int i=l;i<=r;i++) if (q[i].op==1&&q[i].x<=mid) ins(q[i].pos,-1); else if (q[i].op==2&&q[i].x<=mid) ins(q[i].pos,1); int tot=0; for (int i=l;i<=r;i++) if (q[i].op==1||q[i].op==2) { if (q[i].x<=mid) { q[i].mark=1; tot++; } else q[i].mark=0; }else { if (q[i].cur+q[i].tmp<q[i].x) { q[i].cur+=q[i].tmp; q[i].mark=0; }else { q[i].mark=1; tot++; } } int la=l,lb=l+tot; for (int i=l;i<=r;i++) if (q[i].mark) tmp[la++]=q[i]; else tmp[lb++]=q[i]; for (int i=l;i<=r;i++) q[i]=tmp[i]; cdq(l,la-1,L,mid); cdq(la,r,mid+1,R); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) { scanf("%d",&a[i]); q[++tot].op=1; q[tot].x=a[i]; q[tot].pos=i; } for (int i=1;i<=m;i++) { char ch[2]; scanf("%s",ch); if (ch[0]=='Q') { int l,r,x; scanf("%d%d%d",&l,&r,&x); q[++tot].op=3; q[tot].l=l; q[tot].r=r; q[tot].x=x; q[tot].id=++num; }else { int x,y; scanf("%d%d",&x,&y); q[++tot].op=2; q[tot].pos=x; q[tot].x=a[x]; a[x]=y; q[++tot].op=1; q[tot].pos=x; q[tot].x=a[x]; } } cdq(1,tot,0,1000000000); for (int i=1;i<=num;i++) printf("%d\n",ans[i]); return 0; }
相关文章推荐
- [树状数组套权值线段树] BZOJ 1901 Zju2112 Dynamic Rankings
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
- 【BZOJ】1901 Zju2112 Dynamic Rankings 树状数组+主席树
- BZOJ 1901(Zju2112 Dynamic Rankings-区间第k大(修改,在线)-函数式线段树)
- Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap
- BZOJ[1901]Zju2112 Dynamic Rankings 树套树(线段树套Splay)
- [bzoj1901][Zju2112]Dynamic Rankings【树套树】【树状数组】【线段树】
- [bzoj]-1901-Zju2112 Dynamic Rankings-可持久化线段树
- 【BZOJ 1901】Zju2112 Dynamic Rankings &&【COGS 257】动态排名系统 树状数组套线段树
- bzoj 1901: Zju2112 Dynamic Rankings (树状数组套线段树)
- bzoj 1901: Zju2112 Dynamic Rankings(带修改的区间第k大,树状数组+主席树)
- BZOJ_1901_Zju2112 Dynamic Rankings_树状数组+主席树
- bzoj1901 Zju2112 Dynamic Rankings
- BZOJ 1901 Zju 2112 Dynamic Rankings 与更改的树董事长
- 【bzoj1901】Zju2112 Dynamic Rankings
- 【BZOJ 1901】 Zju2112 Dynamic Rankings 主席树+树状数组
- bzoj1901 Zju2112 Dynamic Rankings
- bzoj 1901: Zju2112 Dynamic Rankings(树套树)
- Bzoj1901 Zju2112 Dynamic Rankings
- [BZOJ1901][ZJU2112]Dynamic Rankings