bzoj2683 简单题 cdq分治+树状数组

题目链接:戳这里

2683: 简单题

Time Limit: 50 Sec  Memory Limit: 128 MB
Submit: 1877  Solved: 762
[ Submit][ Status][ Discuss]

Description

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

终止程序

Input

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

Output

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

Sample Input

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

Sample Output

3
5

HINT

1<=N<=500000,操作数不超过200000个,内存限制20M。

对于100%的数据,操作1中的A不超过2000。
题解:如果这题的范围小一点就可以二维bit了...但这题的数据范围显然二维的数据结构无法接受。

于是考虑cdq分治,但我cdq分治实在是太菜了,只能给出按照什么排序QAQ。

对于每个询问,按(x,y,opt)排序。

正常的cdq分治即可,用树状数组维护答案。

代码:

#include<bits/stdc++.h>
#define maxn 200005
#define maxm 500005
#define Q q[tot]
using namespace std;
typedef long long LL;
int read()
{
	char c;int sum=0,f=1;c=getchar();
	while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0' && c<='9'){sum=sum*10+c-'0';c=getchar();}
	return sum*f;
}
int n,tot,t;
int c[maxm],ans[maxn];
void add(int x,int v){for(;x<=n;x+=x&(-x))c[x]+=v;}
int sum(int x){int ret=0;for(;x;x-=x&(-x))ret+=c[x];return ret;}
struct node{
	int opt,x,y,val,id,bel;
}q[maxn<<2],tmp[maxn<<2];
bool cmp(node a,node b)
{
	if(a.x==b.x)
	{
		if(a.y==b.y)
		return a.opt<b.opt;
		return a.y<b.y;
	}
	return a.x<b.x;
}
void cdq(int l,int r)
{
	if(l==r) return;
	int mid=l+r>>1;
	for(int i=l;i<=r;i++)
	{
		if(q[i].opt==1 && q[i].id<=mid) add(q[i].y,q[i].val);
		if(q[i].opt==2 && q[i].id>mid) ans[q[i].bel]+=sum(q[i].y)*q[i].val;
	}
	for(int i=l;i<=r;i++)
	if(q[i].opt==1 && q[i].id<=mid) add(q[i].y,-q[i].val);
	int l1=l,l2=mid+1;
	for(int i=l;i<=r;i++)
	{
		if(q[i].id<=mid)
		tmp[l1++]=q[i];
		else tmp[l2++]=q[i];
	}
	for(int i=l;i<=r;i++)
	q[i]=tmp[i];
	cdq(l,mid);cdq(mid+1,r);
}
int main()
{
	n=read();
	while(1)
	{
		int op=read();
		if(op==3) break;
		if(op==1)
		{
			q[++tot].opt=1;Q.x=read();Q.y=read();Q.val=read();Q.id=tot;
		}
		else
		{
			int X1=read(),Y1=read(),X2=read(),Y2=read();
			q[++tot].opt=2,Q.x=X1-1,Q.y=Y1-1,Q.val=1,Q.id=tot,Q.bel=++t;
            q[++tot].opt=2,Q.x=X1-1,Q.y=Y2,Q.val=-1,Q.id=tot,Q.bel=t;
            q[++tot].opt=2,Q.x=X2,Q.y=Y1-1,Q.val=-1,Q.id=tot,Q.bel=t;
            q[++tot].opt=2,Q.x=X2,Q.y=Y2,Q.val=1,Q.id=tot,Q.bel=t;
		}
	}
	sort(q+1,q+1+tot,cmp);
	cdq(1,tot);
	for(int i=1;i<=t;i++)
	printf("%d\n",ans[i]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39791208/article/details/79142429