BZOJ 1176: [Balkan2007]Mokia

BZOJ 1176: [Balkan2007]Mokia

标签(空格分隔): OI BZOJ cdq分治 分治 树状数组


Time Limit: 30 Sec
Memory Limit: 162 MB


Description

维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数Q<=10000,W<=2000000.

Input

第一行两个整数,S,W;其中S为矩阵初始值;W为矩阵大小

接下来每行为一下三种输入之一(不包含引号):

"1 x y a"

"2 x1 y1 x2 y2"

"3"

输入1:你需要把(x,y)(第x行第y列)的格子权值增加a

输入2:你需要求出以左上角为(x1,y1),右下角为(x2,y2)的矩阵内所有格子的权值和,并输出

输入3:表示输入结束

Output

对于每个输入2,输出一行,即输入2的答案

Sample Input

0 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

保证答案不会超过int范围


Solution####

cdq分治+树状数组 \(O(n*log_2n)\)。2008年cdq的国家集训队作业有相关资料


Code####

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<set>
#include<map>
#include<bitset>
#include<vector>
using namespace std;
#define PA pair<int,int>
const int N=0,M=0;
int read()
{int s=0,f=1;char ch=getchar();
 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+ch-'0';ch=getchar();}
 return s*f;
}
//smile please
int n,T,m;
struct que
{
	bool ask;int x,y,s,t,h;
}q[800005];int qs;
bool operator<(que a,que b)
{
	return a.x<b.x||(a.x==b.x&&a.ask<b.ask);
}
int s[2000005];
que *a[800005];
que *aa[800005];
int ans[200005];
void gb(int l,int r)
{
	int mid=l+r>>1;
	int i=l,j=mid+1,k=l;
	for(int i=l;i<=r;i++)
	   aa[i]=a[i];
	while(i!=mid+1||j!=r+1)
	  {if(i==mid+1)a[k++]=aa[j++];
	   else if(j==r+1)a[k++]=aa[i++];
	   else if(*aa[i]<*aa[j])a[k++]=aa[i++];
	   else a[k++]=aa[j++];
	  }
}
void cdq(int l,int r)
{
	if(l==r)return;
	int mid=l+r>>1;
	cdq(l,mid);cdq(mid+1,r);
	gb(l,r);
	for(int i=l;i<=r;i++)
	   {que now=*a[i];
	    if(now.ask)
	     {if(now.h<=mid)continue;
	      int sum=0;
		  for(int x=now.y;x;x-=x&-x)
	         sum+=s[x];
	      ans[now.t]+=sum*now.s;
		 }
	   else
	     {if(now.h>mid)continue;
	      for(int x=now.y;x<=n;x+=x&-x)
	         s[x]+=now.s;
		 }
	   }
	for(int i=l;i<=r;i++)
	   {que now=*a[i];
	    if(!now.ask)
	      {if(now.h>mid)continue;
	       for(int x=now.y;x<=n;x+=x&-x)
	          s[x]=0;
		  }
	   }
}
int main()
{
	m=read();n=read();T=1;
	for(int op=read();op!=3;op=read(),++T)
	    if(op==1)
	      q[++qs]=(que){0,read(),read(),read(),T,qs},ans[T]=-1;
		else
		  {int x1=read(),y1=read(),x2=read(),y2=read();
		   q[++qs]=(que){1,x2,y2,1,T,qs};
		   q[++qs]=(que){1,x2,y1-1,-1,T,qs};
		   q[++qs]=(que){1,x1-1,y2,-1,T,qs};
		   q[++qs]=(que){1,x1-1,y1-1,1,T,qs};
		   ans[T]+=(x2-x1)*(y2-y1)*m;
		  }
	for(int i=1;i<=qs;i++)a[i]=&q[i];
	cdq(1,qs);
	for(int i=1;i<T;i++)
	   if(ans[i]!=-1)
	     printf("%d\n",ans[i]);
	return 0;
}

posted on 2016-03-03 15:19  wuyuhan  阅读(178)  评论(0编辑  收藏  举报

导航