bzoj 2683 CDQ分治

题目描述

你有一个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

终止程序


输入格式

输入文件第一行一个正整数N。
接下来每行一个操作。
 

输出格式

对于每个2操作,输出一个对应的答案。
 

样例输入

4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
 

样例输出

3
5
 

提示

1<=N<=500000,操作数不超过200000个,内存限制20M。
对于100%的数据,操作1中的A不超过2000。
 
思路分析 :
  CDQ分治真有意思!
  这个题目我们只需要将所给的条件变换一下,不就变成了一道裸的题目啦,题目所给的是在一个二维的空间中,我们可以加一维时间在上边,变成一个三维偏序。
代码示例 : (未测试)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 6e5+5;

int n;
int k = 1;
struct node
{
	int x, y, z, num, sum;
	node(int _x=0, int _y=0, int _z=0, int _num=0, int _sum=0):x(_x),y(_y),z(_z),num(_num),sum(_sum){}

	bool operator< (const node &v)const{
		if (x != v.x) return x < v.x;
		if (y != v.y) return y < v.y;
		return z < v.z; 
	}
}arr[maxn], f[maxn];
int c[maxn];
int lowbit(int x){return x&(-x);}
void add(int p, int num){
	for(int i = p; i <= n; i += lowbit(i)) c[i] += num; 
}
int query(int x){
	int res = 0;
	for(int i = x; i ; i -= lowbit(i)){
		res += c[i];
	}
	return res;
}
void CDQ(int l, int r){
	if (l == r) return;
	int mid = (l+r)>>1;
	CDQ(l, mid);
	CDQ(mid+1, r);
	int	p1 = l, p2 = mid+1;
	int num = 0;
	for(int i = l; i <= r; i++){
		if (p1<=mid && (p2 > r || arr[p1].y <= arr[p2].y)){
			add(arr[p1].z, arr[p1].num);
			f[num++] = arr[p1++];
		}
		else {
			int num2 = query(arr[p2].z);
			arr[p2].sum += num2;
			f[num++] = arr[p2++];
		}
	}
	num = 0;
	for(int i = l; i <= r; i++){
		if (i <= mid) add(arr[i].z, -arr[i].num);
		arr[i] = f[num++];
	}
}

vector<int>ve;
int main () {
	int pt;
	int x1, y1, x2, y2, num;
	int time = 1;
	cin >> n;
	
	while(1){
		scanf("%d", &pt);
		if (pt == 3) break;
		else if (pt == 1) {
			scanf("%d%d%d", &x1, &y1, &num);
			x1++, y1++;
			arr[k++] = node(time++, x1, y1, num, num);			
		}
		else {
			scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
			x1++, y1++, x2++, y2++;
			ve.push_back(k);
			arr[k++] = node(time, x1-1, y1-1, 0, 0);
			arr[k++] = node(time, x1-1, y2, 0, 0);
			arr[k++] = node(time, x2, y1-1, 0, 0);
			arr[k++] = node(time++, x2, y2, 0, 0);
		}
	}
	CDQ(1, k-1);sort(arr+1, arr+k);

	
	for(int i = 0; i < ve.size(); i++){
		int x = ve[i];
		int ans = arr[x+3].sum+arr[x].sum-arr[x+1].sum-arr[x+2].sum;
		printf("%d\n", ans);
	}
	return 0;
}
/*
10
2 1 1 3 3
1 1 1 1
1 2 1 2
1 3 3 1
1 4 4 4
2 1 1 3 3
2 1 1 4 4
3
*/

 

 
posted @ 2018-08-24 19:08  楼主好菜啊  阅读(166)  评论(0编辑  收藏  举报