浅谈整体二分
来源:互联网 发布:盘石网络 编辑:程序博客网 时间:2024/05/17 21:43
整体二分这一算法出自许昊然同学的2013年信息学国家队论文《浅谈数据结构题的几个非经典算法》。其优点在于简短的代码量,可以在较低的代价下,简化很多需要使用复杂数据结构的问题。
不同于传统的数据结构题的解题方法,整体二分是将所有操作进行二分,然后采用分治的思想来解决问题。
问题能使用整体二分的前提:
1.满足修改操作对询问的贡献独立,修改操作之间互不影响结果。
2.题目没有强制在线。
那么前提1是什么意思呢?就是说,每一个修改,只对询问的结果产生影响,而不影响其他修改操作。
我们考虑对要执行的操作分成两部分,可以发现,在前一半操作中,所有的询问都不会收到后一半的影响,这样我们可以递归处理。后一半中的修改也是和前一半无关的,而所有查询操作则是受到前一半中所有修改操作的影响的。这样,后半部分的问题就简化为了一个先操作再询问的问题,问题也就离线化了。
而我们离线化所需要的时间开销,在许昊然论文中证明如下
所以,我们可以以一个log的开销来极大的降低我们的编码难度,将一些需要复杂的高级数据结构问题简化。
伪代码如下:
ZOJ-2112 模版题代码
#include <stdio.h>#include <bits/stdc++.h>using namespace std;const int N = 50005;const int M = 20005;const int INF = 1e9;struct Query{ int id,op,x,y,k;}q[N+M],q1[N+M],q2[N+M];int ans[N],c[N],a[N];void Add(int i,int x){ for(;i<N;i+=(i&(-i))) c[i]+=x;}int Sum(int i){ int res=0; for(;i>0;i-=(i&(-i))) res+=c[i]; return res;}void solve(int ql,int qr,int l,int r){ if(ql>qr) return ; if(l==r){ for(int i=ql;i<=qr;i++) if(q[i].op==2) ans[q[i].id]=l; return ; } int m=l+r>>1,f=0,g=0; for(int i=ql;i<=qr;i++) if(q[i].op==1){ if(q[i].k<=m){ Add(q[i].x,q[i].id); q1[f++]=q[i]; }else q2[g++]=q[i]; }else if(q[i].op==2){ int cnt=Sum(q[i].y)-Sum(q[i].x-1); if(q[i].k<=cnt) q1[f++]=q[i]; else{ q[i].k-=cnt; q2[g++]=q[i]; } } for(int i=0;i<f;i++) if(q1[i].op==1) Add(q1[i].x,-q1[i].id); memcpy(q+ql,q1,f*sizeof(Query)); memcpy(q+ql+f,q2,g*sizeof(Query)); solve(ql,ql+f-1,l,m); solve(ql+f,qr,m+1,r);}int main(){ int T; scanf("%d",&T); while(T--){ int n,m,cnt=1,qq=1; memset(c,0,sizeof c); scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); q[cnt++]=(Query){1,1,i,i,a[i]}; } char opt; int x,y,k; for(int i=1;i<=m;i++){ scanf(" %c %d %d",&opt,&x,&y); if(opt=='C'){ q[cnt++]=(Query){-1,1,x,x,a[x]}; q[cnt++]=(Query){1,1,x,x,y}; a[x]=y; }else if(opt=='Q'){ scanf("%d",&k); q[cnt++]=(Query){qq++,2,x,y,k}; } } solve(1,cnt-1,0,INF); for(int i=1;i<qq;i++) printf("%d\n",ans[i]); } return 0;}
整体二分入门题:
Poj2104
Bzoj3110
Hdu5412
下面这个博客代码写的很好,我的代码就是仿照他的学习的。
大神的博客
阅读全文
0 0
- 浅谈整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分(二分进阶)
- BZOJ1901【整体二分】
- BZOJ2527【整体二分】
- 整体二分入门
- 复习一下整体二分
- 【bzoj2527】Meteors【整体二分】
- POJ 2104【整体二分】
- 整体二分小结
- 【辅助算法】整体二分
- 整体二分初步
- POJ2104 整体二分、树套树
- 李超线段树
- LMS算法学习总结
- operator=与复制操作
- 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。
- JAVA 攻城狮 第二十九天
- 浅谈整体二分
- maven的模块xml配置
- iOS基础之路之addsubview和insertSubView
- bzoj1338: Pku1981 Circle and Points单位圆覆盖
- poj 3461
- 跨域源资源共享CORS
- 在 Linux 中如何自动批量创建用户
- Linux -自动安装系统
- (13)xml入门三