整体二分
来源:互联网 发布:阿里云学生机免费两年 编辑:程序博客网 时间:2024/03/29 21:47
hdu5412
题意:求区间第k小数,支持单点更新
1)将操作定义为3种:添加、删除、询问
2)对于所有操作二分答案m,如果添加/删除操作数
#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>#include<iostream>#define ll long longusing namespace std;const int maxn = 500000+10;const int INF = 0x3f3f3f3f;struct query{ int x,y,k,s,tp,cur;}q[maxn],q1[maxn],q2[maxn];int a[maxn],ans[maxn],tmp[maxn],t[maxn];int n,m,num,cnt;void add(int x,int y){ for(int i=x;i<=n;i+=(i&-i)) t[i]+=y;}int ask(int x){ int tmp=0; for(int i=x;i>0;i-=(i&-i)) tmp+=t[i]; return tmp;}void divide(int head,int tail,int l,int r){ if(head>tail) return; if(l==r){//得到二分答案l,如果是询问操作,添加答案 for(int i=head;i<=tail;i++) if(q[i].tp==3) ans[q[i].s]=l; return; } int m=(l+r)>>1; for(int i=head;i<=tail;i++){//对不大于m的数字进行操作 if(q[i].tp==1&&q[i].y<=m) add(q[i].x,1);//1:在第x个数字上添加y else if(q[i].tp==2&&q[i].y<=m) add(q[i].x,-1);//2:在第x个数字上删除y else if(q[i].tp==3) tmp[i]=ask(q[i].y)-ask(q[i].x-1);//操作区间[q[i].x,min(q[i].y,tail)]内不大于m的数字个数 } for(int i=head;i<=tail;i++){//还原BIT if(q[i].tp==1&&q[i].y<=m) add(q[i].x,-1); else if(q[i].tp==2&&q[i].y<=m) add(q[i].x,1); } int l1=0,l2=0; for(int i=head;i<=tail;i++){ if(q[i].tp==3){//询问操作 if(q[i].cur+tmp[i]>q[i].k-1) q1[++l1]=q[i];//当前区间不大于m的数字个数不小于k,答案在[l,m]区间,加入q1数组 else q[i].cur+=tmp[i],q2[++l2]=q[i];//当前区间不大于m的数字个数小于k,答案在[m+1,r]区间,加入q2数组 } else{//添加/删除操作 if(q[i].y<=m) q1[++l1]=q[i];//操作数字不大于m,影响[l,m]区间答案,加入q1数组 else q2[++l2]=q[i];//操作数字大于m,影响[m+1,r]区间答案,加入q2数组 } } for(int i=1;i<=l1;i++) q[head+i-1]=q1[i]; for(int i=1;i<=l2;i++) q[head+l1+i-1]=q2[i]; divide(head,head+l1-1,l,m); divide(head+l1,tail,m+1,r);}int main(){ //freopen("a.txt","r",stdin); while(scanf("%d",&n)!=EOF){ num=cnt=0; memset(q,0,sizeof(q)); memset(t,0,sizeof(t)); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); q[++num].x=i,q[num].y=a[i],q[num].tp=1,q[num].s=0;//1:添加第x个数字y } scanf("%d",&m); for(int i=1;i<=m;i++){ int d; scanf("%d",&d); if(d==2){ int x,y,z; scanf("%d%d%d",&x,&y,&z); q[++num].x=x,q[num].y=y,q[num].k=z; q[num].tp=3,q[num].s=++cnt;//3:[x,y]区间询问第k大,s:第s个询问 } else{ int x,y; scanf("%d%d",&x,&y); q[++num].x=x,q[num].y=a[x]; q[num].tp=2,q[num].s=0;//2:删除第x个数字y q[++num].x=x,q[num].y=y; q[num].tp=1,q[num].s=0;//1;添加x个数字y a[x]=y;//将第x个数字改成y } } divide(1,num,0,INF);//共num个操作,在[0,INF]上进行二分 for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]); } return 0;}
0 0
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分
- 整体二分(二分进阶)
- BZOJ1901【整体二分】
- BZOJ2527【整体二分】
- 整体二分入门
- 复习一下整体二分
- 【bzoj2527】Meteors【整体二分】
- POJ 2104【整体二分】
- 整体二分小结
- 【辅助算法】整体二分
- 整体二分初步
- POJ2104 整体二分、树套树
- hdu5808 整体二分
- 【内存优化】避免使用Enum
- 关于UIautomator API及浅析
- Smali语法详解
- 使用VM 10安装虚拟机之一(windows xp)
- iOS 9 出现的问题
- 整体二分
- JSP内置对象及方法
- 加快XCode的编译链接速度(200%+)——XCode编译速度慢的解决方案
- 短信拦截广播
- linux 下用iperf 做网络io性能测试
- 软考中级职称 软件工程师 学习知识点记录
- linux 注意事项
- 黑马程序员————java中基于tcp模拟多客户端上次图片到服务器
- 部分浏览器(如chorme)缓存js的问题解决