1176: [Balkan2007]Mokia
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 2592 Solved: 1161
[Submit][Status][Discuss]
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
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
Sample Output
3
5
5
应该这才是BJ真正意义上的CDQ第一题了吧。。
裸三维偏序问题。。
再推荐一遍【教程】简易CDQ分治教程&学习笔记
重点:三元组(时间,横坐标,纵坐标)
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
void print(int x)
{if(x<0)putchar('-'),x=-x;if(x>=10)print(x/10);putchar(x%10+'0');}
const int N=200100;
struct P{int opt,x,y,pos;ll ans;}p[N];
int W;
inline bool cmp(int x,int y)
{return p[x].x==p[y].x?p[x].y==p[y].y?p[x].opt<p[y].opt:p[x].y<p[x].y:p[x].x<p[y].x;}
ll bit[N*10];
inline void modify(int x,int val)
{if(!x)return ;for(;x<=W;x+=(x&-x))bit[x]+=val;}
inline ll query(int x)
{ll res=0;for(;x;x-=(x&-x))res+=bit[x];return res;}
int tot;
int a[N],tmp[N];
void cdq(int l,int r)
{
if(l==r)return ;
int mid=(l+r)>>1;
cdq(l,mid);cdq(mid+1,r);
register int i=l,j=mid+1;
while(j<=r)
{
while(i<=mid&&p[a[i]].x<=p[a[j]].x){if(p[a[i]].opt==1)modify(p[a[i]].y,p[a[i]].ans);i++;}
if(p[a[j]].opt>1)p[a[j]].ans+=query(p[a[j]].y);j++;
}
while(i>l){i--;if(p[a[i]].opt==1)modify(p[a[i]].y,-p[a[i]].ans);}
i=l,j=mid+1;int top=l-1;
while(j<=r||i<=mid)
{
if(i>mid)tmp[++top]=a[j++];
else if(j>r||p[a[i]].x<=p[a[j]].x)tmp[++top]=a[i++];
else tmp[++top]=a[j++];
}
memcpy(a+l,tmp+l,sizeof(int)*(r-l+1));
}
int qnum;
ll ans[N];
int main()
{
ll S=read();W=read();
register int opt=read(),x,y,x2,y2,val,i;
while(opt^3)
{
x=read();y=read();
if(opt==1)
{val=read();p[++tot]=(P){1,x,y,0,val};}
else
{
x2=read();y2=read();x--,y--;
p[++tot]=(P){2,x2,y2,++qnum,S*(x2-x)*(y2-y)};
p[++tot]=(P){2,x,y,qnum,0};
p[++tot]=(P){3,x,y2,qnum,0};
p[++tot]=(P){3,x2,y,qnum,0};
}
opt=read();
}
for(i=1;i<=tot;++i)a[i]=i;
cdq(1,tot);
for(i=1;i<=tot;++i)
if(p[i].opt==2)ans[p[i].pos]+=p[i].ans;
else if(p[i].opt==3)ans[p[i].pos]-=p[i].ans;
for(i=1;i<=qnum;++i){print(ans[i]);puts("");}
return 0;
}
/*
0 4
1 2 3 3
2 1 1 3 3
1 2 2 2
2 2 2 3 4
3
3
5
*/