链接: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;
}