POJ1195/BZOJ1176 题解,CDQ分治
来源:互联网 发布:数据库运维主要做什么 编辑:程序博客网 时间:2024/06/05 15:59
POJ1195 MOBILE/ BZOJ 1176
这两个题题意完全相同,放在一起说吧
题意:
你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:
命令
参数限制
内容
1 x y A
1<=x,y<=N,A是正整数
将格子x,y里的数字加上A
2 x1 y1 x2 y2
1<=x1<= x2<=N
1<=y1<= y2<=N
输出x1 y1 x2 y2这个矩形内的数字和
3
无
终止程序
标准的三维偏序问题,三个维度分别为x,y和时间t。
在POJ1195中,N<=1024,可以用二维树状数组来做,非常简单。
但在BZOJ1176中,N<=500000,空间开不下,所以用CDQ分治+一维树状数组来做。
对于所有的查询操作,我们拆分成4个。分别查询(0,0)到(x1-1,y1-1),(x2,y2),(x2,y1-1),(x1-1,y2)四个矩形的数字和
然后用容斥原理加减一下就可以算出(x1,y1),(x2,y2)的矩形数字和了。
CDQ分治中,首先按x来排序,对t这个维度进行分治。
那么t<=mid的更新操作都能影响到t'>=mid+1的查询结果。
所以在CDQ(l,r)中,按照x从小到大扫一遍所有操作,遇到更新操作就在树状数组上插入y值,
遇到查询操作就给该操作的结果加上树状数组上查询到的sum(1,y)的值。
接下来用类似归并排序的方法,把t<=mid的操作都放到数组左半部分,t>=mid+1的操作都放到右半部分
这么做之后两半部分的x依然是有序的,就可以递归处理两半部分之间的更新操作对查询操作产生的影响了。
下面是代码,按照POJ1195的输入格式写的
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#define ll long longusing namespace std;int n;int tree[1029];int cnt=0;int anscnt=0;int ans[60111]; struct operation{int x,y;int k;int id,ansid; bool type;//0,add;1,query operation(int x_,int y_,int k_,bool type_,int id_):x(x_),y(y_),k(k_),type(type_),id(id_){}operation(int x_,int y_,int k_,int ansid_,bool type_,int id_):x(x_),y(y_),k(k_),ansid(ansid_),type(type_),id(id_){}operation(){}bool operator <(const operation& rhs)const{if(x==rhs.x&&y==rhs.y)return type<rhs.type;if(x==rhs.x)return y<rhs.y;return x<rhs.x;}}op[241111],temp[241111];void add(int x,int k){for(x;x<=n;x+=x&-x)tree[x]+=k;}int query(int x){int res=0;for(x;x>0;x-=x&-x)res+=tree[x];return res;}void cdq(int l,int r){//cout<<l<<" "<<r<<endl;if(l==r)return;int mid=l+r>>1,lp=l,rp=mid+1;for(int i=l;i<=r;++i){if(op[i].id<=mid&&!op[i].type)add(op[i].y,op[i].k);if(op[i].id>mid&&op[i].type)ans[op[i].ansid]+=query(op[i].y)*op[i].k;}for(int i=l;i<=r;++i)if(op[i].id<=mid&&!op[i].type)add(op[i].y,-op[i].k);for(int i=l;i<=r;++i)if(op[i].id<=mid)temp[lp++]=op[i];else temp[rp++]=op[i];for(int i=l;i<=r;++i)op[i]=temp[i];cdq(l,mid);cdq(mid+1,r);}int main(){int o;while(scanf("%d",&o),o!=3){int x,y,k,x2,y2;if(o==0)scanf("%d",&n);if(o==1){scanf("%d%d%d",&x,&y,&k);++cnt;op[cnt]=operation(x+1,y+1,k,0,cnt);}else if(o==2){scanf("%d%d%d%d",&x,&y,&x2,&y2);anscnt++;++cnt;op[cnt]=operation(x2+1,y2+1,1,anscnt,1,cnt);++cnt;op[cnt]=operation(x,y2+1,-1,anscnt,1,cnt);++cnt;op[cnt]=operation(x2+1,y,-1,anscnt,1,cnt);++cnt;op[cnt]=operation(x,y,1,anscnt,1,cnt);}}sort(op+1,op+cnt+1);cdq(1,cnt);for(int i=1;i<=anscnt;++i)printf("%d\n",ans[i]);return 0;}
0 0
- POJ1195/BZOJ1176 题解,CDQ分治
- 【BOI2007】BZOJ1176 CDQ分治
- CDQ分治 【bzoj2683 && bzoj1176】
- [BZOJ1176]-Mokia-CDQ分治
- BZOJ1176【CDQ分治】【树状数组】
- BZOJ1176: [Balkan2007]Mokia CDQ分治
- BZOJ1176: [Balkan2007]Mokia CDQ分治
- [BZOJ1176][[Balkan2007]Mokia][CDQ分治]
- Mobile phones - POJ1195 cdq分治
- [BZOJ1176][Balkan2007]Mokia && CDQ分治+树状数组
- [BZOJ1176][Balkan2007]Mokia(cdq分治+bit)
- [BZOJ2683&&BZOJ1176] CDQ分治&&树状数组
- CDQ分治——BZOJ1176 [Balkan2007]Mokia
- [bzoj1176][Balkan2007]Mokia cdq分治+树状数组
- [BZOJ1176][Balkan2007]Mokia-CDQ分治+树状数组
- BZOJ1176: [Balkan2007]Mokia(CDQ分治)
- cdq分治——bzoj1176: [Balkan2007]Mokia/bzoj2683: 简单题
- BZOJ3295/CQOI2011 题解(CDQ分治)
- spring 父子容器
- JS中几种实用的跨域方法原理详解
- 抢金块(gold) 基础dp
- python Socket编程
- Elasticsearch自定义分词插件
- POJ1195/BZOJ1176 题解,CDQ分治
- POJ 1050 To the Max(dp 最大子矩阵和/最大子段和问题)
- uoj#179 线性规划 单纯形法の模板
- [区块链]应用案例之黄金资产证券化Digix白皮书和DGX解读
- linux 操作系统 常用指令 备忘
- Zookeeper简介(一)
- Linux下Tomcat的安装部署
- IBM 存储RAID硬盘离线和数据库损坏怎么处理
- Vue.js