您的位置:首页 > 其它

分治(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公司编写一个程序来计算在某个矩形区域内有多少名用户。

【输入格式】

有三种命令,意义如下:

命令参数意义
0W初始化一个全零矩阵。本命令仅开始时出现一次。
1x y A向方格(x,y)中添加A个用户。A是正整数。
2X1 Y1 X2 Y2查询X1<=x<=X2,Y1<=y<=Y2所规定的矩形中的用户数量
3无参数结束程序。本命令仅结束时出现一次。

【输出格式】

对所有命令2,输出一个一行整数,即当前询问矩形内的用户数量。

【输入样例】

0 4

1 2 3 3

2 1 1 3 3

1 2 2 2

2 2 2 3 4

3

【输出样例】

3

5

【提示】

输入输出意义
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<=2000000

1<=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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: