题意:维护一个W*W的矩阵,每次操作可以增加某格子的权值,或询问某子矩阵的总权值
思路:CDQ模板题吧,点和矩形(4个点)都看成点,然后利用矩阵的前缀和可求出
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn=200200; int s,w; int n; struct Node { int x,y,kind,pos,num; bool operator<(const Node& node) const { return x<node.x; } void toString() { printf(" (%d,%d) k: %d p: %d num: %d\n",x,y,kind,pos,num); } }T[maxn],nT[maxn]; bool cmp(Node a,Node b) { return a.pos<b.pos; } /***********树状数组**************/ int C; int Color[maxn*10],tree[maxn*10]; inline int lowbit(int x) { return x&(-x); } void Add(int p,int v) { for(int i=p;i<=w;i+=lowbit(i)) { if(Color[i]!=C) tree[i]=0; Color[i]=C; tree[i]+=v; } } int Sum(int p) { int ret=0; for(int i=p;i;i-=lowbit(i)) { if(Color[i]==C) ret+=tree[i]; } return ret; } /****************CDQ*********************/ void CDQ(int l,int r) { if(l==r) return; int mid=(l+r)/2; int l1=l,l2=mid+1; for(int i=l;i<=r;i++) { if(T[i].pos<=mid) nT[l1++]=T[i]; else nT[l2++]=T[i]; } memcpy(T+l,nT+l,sizeof(T[0])*(r-l+1)); CDQ(l,mid); /// 左半部分对右半部分的影响 int j=l; C++; for(int i=mid+1;i<=r;i++) { for(;T[j].x<=T[i].x&&j<=mid;j++) { if(T[j].kind==1) { Add(T[j].y,T[j].num); } } if(T[i].kind==2) { T[i].num+=Sum(T[i].y); } } CDQ(mid+1,r); /// Recover l1=l,l2=mid+1; for(int i=l;i<=r;i++) { if((T[l1]<T[l2]&&l1<=mid)||l2>r) nT[i]=T[l1++]; else nT[i]=T[l2++]; } memcpy(T+l,nT+l,sizeof(T[0])*(r-l+1)); } int main() { scanf("%d%d",&s,&w); int k,x1,y1,x2,y2,S; while(scanf("%d",&k)&&k!=3) { if(k==1) { scanf("%d%d%d",&x1,&y1,&S); n++; T[n]=(Node){x1,y1,1,n,S}; } else if(k==2) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); /// Add 4 Node n++; T[n]=(Node){x1-1,y1-1,2,n,0}; n++; T[n]=(Node){x1-1,y2, 2,n,0}; n++; T[n]=(Node){x2,y1-1, 2,n,0}; n++; T[n]=(Node){x2,y2, 2,n,0}; } } sort(T+1,T+1+n); CDQ(1,n); sort(T+1,T+1+n,cmp); for(int i=1;i<=n;i++) { if(T[i].kind==2) { int ans=0; ans+=T[i].num; i++; ans-=T[i].num; i++; ans-=T[i].num; i++; ans+=T[i].num; printf("%d\n",ans); } } return 0; }