记录编号 314827 评测结果 RRRRRRRRRR
题目名称 [IOI 2001] 移动电话 最终得分 0
用户昵称 GravatarAntiLeaf 是否通过 未通过
代码语言 C++ 运行时间 2.535 s
提交时间 2016-10-04 08:14:32 内存使用 224.40 MiB
显示代码纯文本
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1010;
typedef int point[2];
void madd(point,point,int,int);
void qsum(point,point,int,int);
void pushdown(point,point,int,int);
long long a[maxn*maxn<<4],lazy[maxn*maxn<<4];
int n,m;
long long d,ans;
point x,s,t,L,R;
int main(){
#define MINE
#ifdef MINE
	freopen("notmobile.in","r",stdin);
	freopen("notmobile.out","w",stdout);
#endif
	memset(a,0,sizeof(a));
	memset(lazy,0,sizeof(lazy));
	scanf("%d%d",&n,&m);
	L[0]=L[1]=1;
	R[0]=R[1]=n;
	while(m--){
		scanf("%lld%d%d%d%d",&d,&s[0],&s[1],&t[0],&t[1]);
		if(d==1ll){
			scanf("%lld",&d);
			madd(L,R,1,0);
		}
		else{
			ans=0ll;
			qsum(L,R,1,0);
			printf("%lld\n",ans);
		}
	}
#ifndef MINE
	printf("\n-------------------------DONE-------------------------\n");
	for(;;);
#endif
	return 0;
}
void madd(point l,point r,int rt,int k){
	//printf("(%d,%d)-(%d,%d) k=%d\n",l[0],l[1],r[0],r[1],k);
	//printf("rt=%d a[rt]=%lld lazy[rt]=%lld\n",rt,a[rt],lazy[rt]);
	if(s[0]<=l[0]&&t[0]>=r[0]&&s[1]<=l[1]&&t[1]>=r[1]){
		lazy[rt]+=d;
		a[rt]+=lazy[rt]*(long long)(r[0]-l[0]+1)*(long long)(r[1]-l[1]+1);
		return;
	}
	if(l[0]==r[0])k=1;
	else if(l[1]==r[1])k=0;
	pushdown(l,r,rt,k);
	if(k==0){
		//printf("lc:(%d,%d)-(%d,%d)\n",l[0],l[1],(l[0]+r[0])>>1,r[1]);
		//printf("rc:(%d,%d)-(%d,%d)\n",((l[0]+r[0])>>1)+1,l[1],r[0],r[1]);
	}
	else{
		//printf("lc:(%d,%d)-(%d,%d)\n",l[0],l[1],r[0],(l[1]+r[1])>>1);
		//printf("rc:(%d,%d)-(%d,%d)\n",l[0],((l[1]+r[1])>>1)+1,r[0],r[1]);
	}
	//printf("\n");
	point mid;
	if(s[k]<=((l[k]+r[k])>>1)){
		mid[k]=(l[k]+r[k])>>1;
		mid[k^1]=r[k^1];
		madd(l,mid,rt<<1,k^1);
	}
	if(t[k]>((l[k]+r[k])>>1)){
		mid[k]=((l[k]+r[k])>>1)+1;
		mid[k^1]=l[k^1];
		madd(mid,r,rt<<1|1,k^1);
	}
	a[rt]=a[rt<<1]+a[rt<<1|1];
	//printf("back to (%d,%d)-(%d,%d) k=%d\n",l[0],l[1],r[0],r[1],k);
	//printf("rt=%d a[rt]=%lld lazy[rt]=%lld\n",rt,a[rt],lazy[rt]);
	//printf("\n");
}
void qsum(point l,point r,int rt,int k){
	//printf("(%d,%d)-(%d,%d) k=%d\n",l[0],l[1],r[0],r[1],k);
	//printf("rt=%d a[rt]=%lld lazy[rt]=%lld\n",rt,a[rt],lazy[rt]);
	if(s[0]<=l[0]&&t[0]>=r[0]&&s[1]<=l[1]&&t[1]>=r[1]){
		ans+=a[rt];
		return;
	}	
	if(l[0]==r[0])k=1;
	else if(l[1]==r[1])k=0;
	pushdown(l,r,rt,k);
	point mid;
	if(k==0){
		//printf("lc:(%d,%d)-(%d,%d)\n",l[0],l[1],(l[0]+r[0])>>1,r[1]);
		//printf("rc:(%d,%d)-(%d,%d)\n",((l[0]+r[0])>>1)+1,l[1],r[0],r[1]);
	}
	else{
		//printf("lc:(%d,%d)-(%d,%d)\n",l[0],l[1],r[0],(l[1]+r[1])>>1);
		//printf("rc:(%d,%d)-(%d,%d)\n",l[0],((l[1]+r[1])>>1)+1,r[0],r[1]);
	}
	//printf("\n");//getchar();
	if(s[k]<=((l[k]+r[k])>>1)){
		mid[k]=(l[k]+r[k])>>1;
		mid[k^1]=r[k^1];
		qsum(l,mid,rt<<1,k^1);
	}
	if(t[k]>((l[k]+r[k])>>1)){
		mid[k]=((l[k]+r[k])>>1)+1;
		mid[k^1]=l[k^1];
		qsum(mid,r,rt<<1|1,k^1);
	}
	//printf("back to (%d,%d)-(%d,%d) k=%d\n",l[0],l[1],r[0],r[1],k);
	//printf("rt=%d a[rt]=%lld lazy[rt]=%lld\n",rt,a[rt],lazy[rt]);
	//printf("\n");
}
void pushdown(point l,point r,int rt,int k){
	if(!lazy[rt])return;
	//printf("pushdown(%d)\n",rt);
	int lc=rt<<1,rc=rt<<1|1;
	point mid;
	mid[k]=(l[k]+r[k])>>1;
	mid[k^1]=r[k^1];
	a[lc]+=lazy[rt]*(mid[k]-l[k]+1)*(mid[k^1]-l[k^1]+1);
	lazy[lc]+=lazy[rt];
	mid[k]=((l[k]+r[k])>>1)+1;
	mid[k^1]=l[k^1];
	a[rc]+=lazy[rt]*(r[k]-mid[k]+1)*(r[k^1]-mid[k^1]+1);
	lazy[rc]+=lazy[rt];
	lazy[rt]=0ll;
}
/*
5 8
1 1 1 2 2 1
2 2 2 3 3
1 1 5 2 5 3
2 1 1 5 2
2 2 3 4 5
1 1 1 1 1 7
1 4 5 5 5 4
2 2 2 4 5
Answer:
1
4
3
8
*/
/*
我们尝试使用类似K-D树的方式劈区间,
把当前区间轮流横劈和竖劈,
这样就可以完美地解决二维问题啦。
*/