[BZOJ 1176][Balkan2007]Mokia
CDQ分治第一题……同时也是CDQ分治模板提。
感觉CDQ分治思路好秒啊……似乎在分治过程中做了个归并排序……
代码:
/**************************************************************
Problem: 1176
User: danihao123
Language: C++
Result: Accepted
Time:4364 ms
Memory:17228 kb
****************************************************************/
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxw=2000005;
const int maxq=10005;
const int maxn=160001+4*maxq;
int cnt=0;
struct Query{
int ans_id;
int x,y,d,v;
Query(){}
Query(int a,int b,int di,int ap){
x=a;y=b;
d=di;
ans_id=ap;
}
Query(int a,int b,int value){
x=a;y=b;
v=value;
d=0;
}
inline bool isQuery(){
return d!=0;
}
};
int w;
int T[maxw];
inline int lowbit(int x){
return x&(-x);
}
inline void add(int p,int v){
while(p<=w){
T[p]+=v;
p+=lowbit(p);
}
}
inline int sum(int p){
register int x=0;
while(p>0){
x+=T[p];
p-=lowbit(p);
}
return x;
}
inline void clear(int p){
while(p<=w && T[p]!=0){
T[p]=0;
p+=lowbit(p);
}
}
Query Q[maxn],tmp[maxn];
int ans[maxn];
void CDQ(int L,int R){
if(L==R){
return;
}
int M=L+(R-L)/2;
CDQ(L,M);
CDQ(M+1,R);
int p,p1,p2;
for(p=1,p1=L,p2=M+1;p<=(R-L+1);p++){
if((Q[p1].x<=Q[p2].x && p1<=M) || p2>R){
tmp[p]=Q[p1];
if(!Q[p1].isQuery()){
add(Q[p1].y,Q[p1].v);
}
p1++;
}else{
tmp[p]=Q[p2];
if(Q[p2].isQuery()){
ans[Q[p2].ans_id]+=sum(Q[p2].y)*Q[p2].d;
}
p2++;
}
}
for(p=1,p1=L;p<=(R-L+1);p++,p1++){
if(!Q[p1].isQuery()){
clear(Q[p1].y);
}
Q[p1]=tmp[p];
}
}
int main(){
int S,t,x,y,a,b;
register int ans_cnt=0;
scanf("%d%d",&S,&w);
while(true){
scanf("%d",&t);
if(t==3){
break;
}
scanf("%d%d%d",&x,&y,&a);
// x++;y++;
if(t==1){
Q[++cnt]=Query(x,y,a);
}else{
scanf("%d",&b);
// a++;b++;
ans_cnt++;
ans[ans_cnt]=(a-x+1)*(b-y+1)*S;
Q[++cnt]=Query(a,b,1,ans_cnt);
Q[++cnt]=Query(x-1,b,-1,ans_cnt);
Q[++cnt]=Query(a,y-1,-1,ans_cnt);
Q[++cnt]=Query(x-1,y-1,1,ans_cnt);
}
}
CDQ(1,cnt);
for(register int i=1;i<=ans_cnt;i++){
printf("%d\n",ans[i]);
}
return 0;
}