1. 程式人生 > >BZOJ2683: 簡單題

BZOJ2683: 簡單題

sam 簡單題 clas 答案 sta time content width online

題解: cdq分治一下即可 把查詢分成四個矩形

#include <bits/stdc++.h>
const int MAXN=8e5+10;
const int NM=5e5+10;
using namespace std;
const int inf=1e9;
typedef struct node{
	int x,y,id,vul;
}node;
node d[MAXN],p[MAXN];int ans[NM];
int sum[NM],n;
int get_id(int x){return x&(-x);}
void add(int x,int vul){
	for(int i=x;i<=n;i+=get_id(i))sum[i]+=vul;
}
int Sum(int x){
	int ans1=0;
	for(int i=x;i>0;i-=get_id(i))ans1+=sum[i];
	return ans1;
}
void clear(int x){
	if(!x)return ;
	for(int i=x;i<=n;i+=get_id(i))sum[i]=0;
}
void merge(int l,int mid,int r){
	int i=l;int j=mid+1;int cnt=0;
	//cout<<l<<"++++"<<r<<endl;
	while(i<=mid&&j<=r){
		while(i<=mid&&d[i].x<=d[j].x){
			if(!d[i].id)add(d[i].y,d[i].vul);
			p[++cnt]=d[i];i++;
		}
		if(d[j].id>0)ans[d[j].id]+=Sum(d[j].y);
		if(d[j].id<0)ans[-1*d[j].id]-=Sum(d[j].y);
		p[++cnt]=d[j];j++;
		//cout<<l<<":::"<<r<<i<<" "<<j<<endl;
	}
	if(j<=r){
		for(;j<=r;j++){
			if(d[j].id>0)ans[d[j].id]+=Sum(d[j].y);
			if(d[j].id<0)ans[-1*d[j].id]-=Sum(d[j].y);
			p[++cnt]=d[j];
		}
	}
	//cout<<"sb"<<endl;
	if(i<=mid){
		for(;i<=mid;i++)p[++cnt]=d[i];
	}
	//cout<<"sb"<<endl;
	for(int i=1;i<=cnt;i++)d[l+i-1]=p[i],clear(p[i].y);
}
void cdq(int l,int r){
	//cout<<l<<" "<<r<<endl;
	if(l>=r)return ;
	int mid=(l+r)>>1;
	cdq(l,mid);
	cdq(mid+1,r);
	merge(l,mid,r);
	//cout<<l<<" "<<r<<" "<<mid<<endl;
	//for(int i=l;i<=r;i++)cout<<d[i].x<<"===="<<d[i].y<<" "<<d[i].id<<endl;
}
int main(){
	scanf("%d",&n);
	int op,x1,x2,y1,y2;int cnt=0,cnt1=0;
	for(int i=1;;i++){
		scanf("%d",&op);
		if(op==3)break;
		cnt1++;
		if(op==1)scanf("%d%d%d",&x1,&y1,&y2),d[++cnt].x=x1,d[cnt].y=y1,d[cnt].id=0,d[cnt].vul=y2,ans[i]=inf;
		else{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);ans[i]=0;
			d[++cnt].x=x2;d[cnt].y=y2;d[cnt].id=i;
			d[++cnt].x=x1-1;d[cnt].y=y1-1;d[cnt].id=i;
			d[++cnt].x=x1-1;d[cnt].y=y2;d[cnt].id=-i;
			d[++cnt].x=x2;d[cnt].y=y1-1;d[cnt].id=-i;
		}
	}
	cdq(1,cnt);
	//cout<<cnt1<<endl;
	for(int i=1;i<=cnt1;i++){
		if(ans[i]!=inf)printf("%d\n",ans[i]);
	}
	return 0;
}

2683: 簡單題

Time Limit: 50 Sec Memory Limit: 128 MB
Submit: 2225 Solved: 916
[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。

BZOJ2683: 簡單題