bzoj 1176 Mokia(CDQ分治)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1176 Mokia(CDQ分治)相关的知识,希望对你有一定的参考价值。
【题目链接】
http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=96974
【题意】
定义查询操作与修改操作:1 x y z 为将格子(x,y)修改为z;2 x1 y1 x2 y2为查询以(x1,y1)为左上(x2,y2)为右下的子矩阵之和。
【思路】
cdq分治。
矩阵初始值都为s,所以先不考虑。
首先明确每一个修改操作都互不影响。然后把每一个对子矩阵的询问操作差分为对四个点的“前缀和”操作。
先把所有的操作按照x升序排列。进行cdq分治。
定义solve(l,r)为解决查询顺序在l,r区间内的操作,且在solve结束后保证区间按照x的递增排列。
1) 将区间按照查询先后顺序重排
2) Solve(l,mid)
3) 计算左区间对右区间的贡献。这时候左区间是按照x升序排列的,右区间是按照查询先后排列的,这样正好既可以保证求贡献时左区间x的单调与递归右区间时右区间内所有的查询都在。对于右区间的i,将左区间内x所有小于它的加入BIT,维护区间和,如果i是询问则查询BIT中所有y小于它的z之和。
4) Solve(mid+1,r)
5) 恢复区间,按照x升序排列
最后答案加上矩阵的s即可。
BIT的清理也可通过加时间戳的方式做到。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 2*1e6+10; 8 const int inf = 1e9+7; 9 10 int n,sz,s,w; 11 int C[N],flag[N],T,tmp[N]; 12 13 struct Node { 14 int x,y,z,pos,ans; 15 bool operator<(const Node& rhs) const{ 16 return x<rhs.x; 17 } 18 Node(int x=0,int y=0,int z=0) { 19 this->x=x,this->y=y,this->z=z; 20 pos=sz; ans=0; 21 } 22 }q[N],t[N]; 23 bool cmp(const Node& x,const Node& y) 24 { 25 return x.pos<y.pos; 26 } 27 28 void add(int x,int v) 29 { 30 for(;x<=w;x+=x&-x) 31 if(flag[x]!=T) flag[x]=T,C[x]=v; 32 else C[x]+=v; 33 } 34 int query(int x) 35 { 36 int res=0; 37 for(;x;x-=x&-x) 38 if(flag[x]==T) res+=C[x]; 39 return res; 40 } 41 42 void solve(int l,int r) 43 { 44 if(l==r) return ; 45 int mid=(l+r)>>1; 46 int l1=l,l2=mid+1,i,j; 47 for(i=l;i<=r;i++) { 48 if(q[i].pos<=mid) t[l1++]=q[i]; 49 else t[l2++]=q[i]; 50 } 51 memcpy(q+l,t+l,sizeof(q[0])*(r-l+1)); 52 solve(l,mid); 53 j=l; T++; 54 for(i=mid+1;i<=r;i++) { 55 for(;j<=mid&&q[j].x<=q[i].x;j++) 56 if(q[j].z!=-inf) add(q[j].y,q[j].z); 57 if(q[i].z==-inf) q[i].ans+=query(q[i].y); 58 } 59 solve(mid+1,r); 60 l1=l,l2=mid+1; int now=l; 61 while(l1<=mid||l2<=r) { 62 if(l2>r||l1<=mid&&q[l1]<q[l2]) t[now++]=q[l1++]; 63 else t[now++]=q[l2++]; 64 } 65 memcpy(q+l,t+l,sizeof(q[0])*(r-l+1)); 66 } 67 68 void read(int &x) 69 { 70 char c=getchar(); x=0;int f=1; 71 while(!isdigit(c)){ if(c==‘-‘)f=-1; c=getchar(); } 72 while(isdigit(c)) x=x*10+c-‘0‘ , c=getchar(); 73 x*=f; 74 } 75 76 int main() 77 { 78 read(s),read(w); 79 int op,x1,y1,x2,y2,z; 80 while(read(op),op!=3) 81 { 82 if(op==1) { 83 read(x1),read(y1),read(z); 84 q[++sz]=(Node){x1,y1,z}; 85 } else { 86 read(x1),read(y1),read(x2),read(y2); 87 q[++sz]=Node(x1-1,y1-1,-inf); 88 tmp[sz]=abs(x1-x2+1)*abs(y1-y2+1)*s; 89 q[++sz]=Node(x1-1,y2,-inf); 90 q[++sz]=Node(x2,y1-1,-inf); 91 q[++sz]=Node(x2,y2,-inf); 92 } 93 } 94 sort(q+1,q+sz+1); 95 solve(1,sz); 96 sort(q+1,q+sz+1,cmp); 97 for(int i=1;i<=sz;i++) if(q[i].z==-inf) { 98 int ans=tmp[i]; 99 ans+=q[i++].ans; 100 ans-=q[i++].ans; 101 ans-=q[i++].ans; 102 ans+=q[i++].ans; 103 i--; 104 printf("%d\n",ans); 105 } 106 return 0; 107 }
ps:鄙人并非权限汪,如代码不能AC概不负责 :)
以上是关于bzoj 1176 Mokia(CDQ分治)的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ 1176&COGS 1752][BOI2007]Mokia(CDQ分治)
cdq分治入门--BZOJ1176: [Balkan2007]Mokia