题目描述
摩尔瓦多的移动电话公司摩基亚(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,输出一个一行整数,即当前询问矩形内的用户数量。

输入输出样例
输入 #1复制

0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
输出 #1复制
3
5
说明/提示
对于所有数据:

1<=W<=2000000
1<=X1<=X2<=W
1<=Y1<=Y2<=W
1<=x,y<=W
0<A<=10000
命令1不超过160000个。
命令2不超过10000个。


一道以时间以一维的cdq分治。应该不难想到。


这道题我们用cdq分治,求类似前缀和,一个查询,我们去用四个前缀和的查询,代替一个非前缀的查询,画画图就能想到。

然后这道题因为我们是求前缀和嘛,所以可能出现边界是0的情况,所以我们让整体加一即可,不然树状数组会死循环。

然后因为我们cdq时对x排序了,所以最后求答案时要返回去,对时间排序即可。


AC代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
//#define int long long
#define lowbit(x) (x&(-x))
using namespace std;
const int N=2e5+10,M=2e6+10;
int d[M],n,tot,res[N];
struct node{
	int tm,x,y,cnt,id;
}t[N];
inline void add(int x,int v){
	for(int i=x;i<M;i+=lowbit(i))	d[i]+=v;	
}
inline int ask(int x){
	int res=0;	for(int i=x;i;i-=lowbit(i))	res+=d[i];	return res;
}
bool cmp(const node &s1,const node &s2){
	return (s1.x==s2.x)?(s1.y<s2.y):(s1.x<s2.x);
}
bool cmpt(const node &s1,const node &s2){
	return s1.tm<s2.tm;
}
void cdq(int l,int r){
	if(l==r)	return ;	int mid=l+r>>1;
	cdq(l,mid);	cdq(mid+1,r);
	sort(t+l,t+mid+1,cmp);	sort(t+mid+1,t+r+1,cmp);
	int j=l;
	for(int i=mid+1;i<=r;i++){
		while(j<=mid&&t[j].x<=t[i].x){
			if(t[j].id)	add(t[j].y,t[j].cnt);
			j++;
		}
		if(!t[i].id)	t[i].cnt+=ask(t[i].y);
	}
	for(int i=l;i<j;i++) if(t[i].id)	add(t[i].y,-t[i].cnt);
}
signed main(){
	scanf("%d %d",&n,&n);
	while(1){
		int op;	scanf("%d",&op);
		if(op==3)	break;
		if(op==1){
			int x,y,a;	scanf("%d %d %d",&x,&y,&a);	++x; ++y;
			t[++tot]={tot,x,y,a,1};
		}else{
			int x1,y1,x2,y2;	scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
			++x2;	++y2;
			t[++tot]={tot,x1,y1,0,0}; t[++tot]={tot,x2,y2,0,0};
			t[++tot]={tot,x1,y2,0,0}; t[++tot]={tot,x2,y1,0,0};
		}
	}
	cdq(1,tot);	sort(t+1,t+1+tot,cmpt);
	for(int i=1;i<=tot;i++){
		if(!t[i].id){
			printf("%d\n",t[i].cnt+t[i+1].cnt-t[i+2].cnt-t[i+3].cnt); i+=3;
		}
	}
	return 0;
}