算得上是CDQ分治三维偏序的模板题了吧QAQ。
我们就把查询操作容斥一下,就变成了求
sum(1,1,x2,y2)−sum(1,1,x1−1,y2)−sum(1,1,x2,y1−1)+sum(1,1,x1−1,y1−1)
那么相当于我们只需要维护一个二维的前缀和。
定义三元组 (t,x,y) t表示时间,x,y分别表示一维。
那么就是要求 (tt,xx,yy) 满足 tt<t,xx<=x,yy<=y 的和。
t是默认有序的,然后以X坐标为序,y用树状数组维护即可。
具体实现中我用了五个值表示状态:
type(0/1) 表示是修改还是查询, x,y 表示两个维度。 w 在修改中表示要增加的值,在查询中
Warning!
1.对于相同的
x
<script type="math/tex" id="MathJax-Element-12">x</script>,要先修改再查询。
2.每一次操作要将树状数组清空。
【代码】
#include <cstdio>
#include <iostream>
#include <algorithm>
#define N 200005
#define INF 0x7fffffff
using namespace std;
typedef long long ll;
ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
int n,m,cnt,tot,na;
int ans[10005],szsz[2000005];
class Ope{
public:
int type,id,num,x,y,w;
Ope(){}
Ope(int tt,int ii,int nn,int xx,int yy,int ww) {
type=tt,id=ii,num=nn,x=xx,y=yy,w=ww;
}
}e[N],tmp[N];
bool operator <(Ope A,Ope B) {
return A.x<B.x||(A.x==B.x&&A.type<B.type);
}
int lowbit(int x) {
return x&-x;
}
void Update(int x,int y) {
for(int i=x;i<=m;i+=lowbit(i)) szsz[i]+=y;
}
int Query(int x) {
int rtn=0;
for(int i=x;i;i-=lowbit(i)) rtn+=szsz[i];
return rtn;
}
void Clear(int x){
for(int i=x;i<=m&&szsz[i];i+=lowbit(i)) szsz[i]=0;
}
void CDQ(int l,int r)
{
if(l==r) return;
int mid=l+r>>1;
CDQ(l,mid);CDQ(mid+1,r);
int p=l,q=mid+1,o=0;
while(p<=mid&&q<=r)
{
if(e[p]<e[q]) {
if(!e[p].type)
Update(e[p].y,e[p].w);
tmp[o++]=e[p++];
}
else
{
if(e[q].type)
ans[e[q].num]+=e[q].w*Query(e[q].y);
tmp[o++]=e[q++];
}
}
while(p<=mid) {
if(!e[p].type)
Update(e[p].y,e[p].w);
tmp[o++]=e[p++];
}
while(q<=r) {
if(e[q].type) ans[e[q].num]+=e[q].w*Query(e[q].y);
tmp[o++]=e[q++];
}
for(int i=0;i<o;i++) {
if(!tmp[i].type&&tmp[i].id<=mid)
Update(tmp[i].y,-tmp[i].w);
e[l+i]=tmp[i];
}
}
int main()
{
n=read(),m=read();
while(1)
{
static int f,x,y,xx,yy;
f=read();if(f==3) break;
else if(f==1) {
x=read(),y=read(),xx=read();
e[++tot]=Ope(0,tot,0,x,y,xx);
}
else {
x=read(),y=read(),xx=read(),yy=read();
e[++tot]=Ope(1,tot,++na,x-1,y-1,1);
e[++tot]=Ope(1,tot,na,x-1,yy,-1);
e[++tot]=Ope(1,tot,na,xx,y-1,-1);
e[++tot]=Ope(1,tot,na,xx,yy,1);
}
}
CDQ(1,tot);
for(int i=1;i<=na;i++) printf("%d\n",ans[i]);
return 0;
}