链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1176
题意:中文题
分析:题目要求一个子矩阵的所有权值和,我们可以将询问用容斥分成四块,
可以通过加加减减得到原矩阵;现在我们把这些询问都成了与修改一样的操作形式,
对于这些操作我们加入一个时间戳z,那么一个修改(x,y,z)会对询问(x1,y1,z1)产生影响的
必要条件就是x<=x1,y<=y1,z<=z1。那么我们对所有操作排个序,我们用cdq分治处理区间[l,r],mid=(l+r)>>1,
所有时间戳小于mid的修改都会对时间戳大于mid的询问产生影响,我们可以用树状数组求出。
排序处理x关系,剩下的就是y和z了,我们用树状数组处理y,cdq处理z。
代码:
#include <algorithm> #include <iostream> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <vector> #include <queue> #include <cmath> #include <stack> #include <set> #include <map> #include <ctime> #define INF 0x3f3f3f3f #define Mn 300010 #define Mm 2000005 #define mod 1000000007 #define CLR(a,b) memset((a),(b),sizeof((a))) #define CPY(a,b) memcpy ((a), (b), sizeof((a))) #pragma comment(linker, "/STACK:102400000,102400000") #define ul (u<<1) #define ur (u<<1)|1 using namespace std; typedef long long ll; struct node { int x,y,z,val,id; node(){} node(int x,int y,int z,int val,int id):x(x),y(y),z(z),val(val),id(id){} bool operator <(const node a) const { if(x!=a.x) return x<a.x; if(y!=a.y) return y<a.y; return z<a.z; } }q[Mn],tmp[Mn]; int bit[Mm]; int n; int lowbit(int x) {return x&(-x);} void push(int x,int val) { if(x==0) return ; while(x<=n) { bit[x]+=val; x+=lowbit(x); } return ; } int sum(int x) { int re=0; while(x>0) { re+=bit[x]; x-=lowbit(x); } return re; } int cnt; int ans[Mn]; stack<pair<int,int> > sk; void cdq(int l,int r) { if(l==r) return ; int mid=(l+r)>>1; for(int i=l;i<=r;i++) { if(q[i].z<=mid&&!q[i].id) push(q[i].y,q[i].val),sk.push(make_pair(q[i].y,q[i].val)); else if(q[i].z>mid&&q[i].id) ans[q[i].id]+=q[i].val*sum(q[i].y); } while(!sk.empty()) { push(sk.top().first,-sk.top().second); sk.pop(); } int L=l,R=mid+1; for(int i=l;i<=r;i++) { if(q[i].z<=mid) { tmp[L]=q[i]; L++; } else { tmp[R]=q[i]; R++; } } for(int i=l;i<=r;i++) q[i]=tmp[i]; cdq(l,mid); cdq(mid+1,r); } int main() { int m,w,x,id; int x1,x2,y1,y2; scanf("%d%d",&m,&n); cnt=id=0; while(scanf("%d",&x)) { if(x==1) { scanf("%d%d%d",&x1,&y1,&w); q[++cnt]=node(x1,y1,cnt,w,0); } else { if(x==3)break; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); ans[++id]+=(y2-y1+1)*(x2-x1+1)*m; q[++cnt]=node(x2,y2,cnt,1,id); q[++cnt]=node(x1-1,y1-1,cnt,1,id); q[++cnt]=node(x1-1,y2,cnt,-1,id); q[++cnt]=node(x2,y1-1,cnt,-1,id); } } sort(q+1,q+cnt+1); cdq(1,cnt); for(int i=1;i<=id;i++) { printf("%d\n",ans[i]); } return 0; }