分治(CDQ):[BOI2007]摩基亚Mokia
2016-03-22 23:01
477 查看
【题目描述】
摩尔瓦多的移动电话公司摩基亚(Mokia)设计出了一种新的用户定位系统。和其他的定位系统一样,它能够迅速回答任何形如“用户C的位置在哪?”的问题,精确到毫米。但其真正高科技之处在于,它能够回答形如“给定区域内有多少名用户?”的问题。在定位系统中,世界被认为是一个W*W的正方形区域,由1*1的方格组成。每个方格都有一个坐标(x,y),1<=x,y<=W。坐标的编号从1开始。对于一个4*4的正方形,就有1<=x<=4,1<=y<=4(如图):
请帮助Mokia公司编写一个程序来计算在某个矩形区域内有多少名用户。
【输入格式】
有三种命令,意义如下:命令 | 参数 | 意义 |
0 | W | 初始化一个全零矩阵。本命令仅开始时出现一次。 |
1 | x y A | 向方格(x,y)中添加A个用户。A是正整数。 |
2 | X1 Y1 X2 Y2 | 查询X1<=x<=X2,Y1<=y<=Y2所规定的矩形中的用户数量 |
3 | 无参数 | 结束程序。本命令仅结束时出现一次。 |
【输出格式】
对所有命令2,输出一个一行整数,即当前询问矩形内的用户数量。【输入样例】
0 41 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
【输出样例】
35
【提示】
输入 | 输出 | 意义 |
0 4 | 大小为4*4的全零正方形 | |
1 2 3 3 | 向(2,3)方格加入3名用户 | |
2 1 1 3 3 | 查询矩形1<=x<=3,1<=y<=3内的用户数量 | |
3 | 查询结果 | |
1 2 2 2 | 向(2,2)方格加入2名用户 | |
2 2 2 3 4 | 查询矩形2<=x<=3,2<=y<=4内的用户数量 | |
5 | 查询结果 | |
3 | 终止程序 |
【数据规模】
1<=W<=20000001<=X1<=X2<=W
1<=Y1<=Y2<=W
1<=x,y<=W
0<A<=10000
命令1不超过160000个。
命令2不超过10000个。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn=200010; const int maxs=2000010; struct Node{ int id,x,y,d,ans; Node(int id_=0,int x_=0,int y_=0,int d_=0,int ans_=0){ id=id_;x=x_;y=y_;d=d_;ans=ans_; } }p[maxn],t[maxn]; int bit[maxs],s,op,cnt; int vis[maxs],dep; void add(int x,int d){ while(x<=s){ if(vis[x]!=dep) bit[x]=0; bit[x]+=d; vis[x]=dep; x+=x&(-x); } } int Query(int x){ int ret=0; while(x){ if(vis[x]==dep) ret+=bit[x]; x-=x&(-x); } return ret; } bool cmp1(Node a,Node b){ return a.x<b.x; } bool cmp2(Node a,Node b){ return a.id<b.id; } void Solve(int l,int r){ if(l==r)return; int mid=(l+r)>>1,t1=l,t2=mid+1; for(int i=l;i<=r;i++){ if(p[i].id<=mid)t[t1++]=p[i]; else t[t2++]=p[i]; } for(int i=l;i<=r;i++)p[i]=t[i]; Solve(l,mid);++dep; for(int i=mid+1,j=l;i<=r;i++){ for(;p[i].x>=p[j].x&&j<=mid;j++) if(p[j].d!=-1) add(p[j].y,p[j].d); if(p[i].d==-1) p[i].ans+=Query(p[i].y); } Solve(mid+1,r); t1=l;t2=mid+1; for(int i=l;i<=r;i++) if(t2==r+1||p[t1].x<p[t2].x&&t1<=mid)t[i]=p[t1++]; else t[i]=p[t2++]; for(int i=l;i<=r;i++)p[i]=t[i]; } int main(){ freopen("mokia.in","r",stdin); freopen("mokia.out","w",stdout); int a,b,x,y; scanf("%d%d",&a,&s); while(~scanf("%d",&op)&&op!=3){ if(op==1){ scanf("%d%d%d",&x,&y,&a); p[++cnt]=Node(cnt,x,y,a); } else{ scanf("%d%d%d%d",&x,&y,&a,&b); p[++cnt]=Node(cnt,a,b,-1); p[++cnt]=Node(cnt,a,y-1,-1); p[++cnt]=Node(cnt,x-1,b,-1); p[++cnt]=Node(cnt,x-1,y-1,-1); } } sort(p+1,p+cnt+1,cmp1); Solve(1,cnt); sort(p+1,p+cnt+1,cmp2); for(int i=1,ret;i<=cnt;i++) if(p[i].d==-1){ ret=0; ret+=p[i].ans; ret-=p[++i].ans; ret-=p[++i].ans; ret+=p[++i].ans; printf("%d\n",ret); } return 0; }
相关文章推荐
- [BZOJ4034][HAOI2015]T2 做题笔记
- 使用 history 对象
- QT 模拟点击网页
- Android中的软引用、弱引用
- 不使用库函数实现字符串复制函数strCopy
- angular-API
- Spring1
- 软考信息系统监理师,2016年3月18日作业
- 如何提高循环效率
- Phantomjs+Nodejs+Mysql数据抓取(2.抓取图片)
- LeetCode 143. Reorder List
- lua gc 优化方案
- Android数据库框架
- 无线AP和无线路由器区别
- Spring IOC
- angular-输入验证
- 无线AP和无线路由器区别
- 分析与设计数据库模型的简单过程
- 【真题索引】2016/03/22知识点整理
- [Java] 实验4参考代码