思路 :按照操作的时间进行分治,这样转化成了 时间t ,x坐标,y坐标 经典的三维偏序。
最初时间就是递增顺序,无需排序直接进行第二维的分治,类似归并排序处理x坐标,在保证
x有序的情况下进行更新y坐标的树状数组。求一个 (x1,y1) - (x2,y2)矩形内点的个数,简单容斥一下
求[ (1,1) ——(x1-1,y1-1) ]+[ (1,1) ——(x2,y2) ]-[ (1,1) ——(x1-1,y1) ]-[ (1,1) ——(x1,y1-1) ]
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxn 2234567 ll op,w,s,x[3],y[3]; ll cnt,q[maxn],tot; ll ans[maxn],tree[maxn]; struct node { int x,y,id,ad; } data[maxn],cp[maxn]; int lowbit(int x) { return x&-x; } void add(int x,int d) { while(x<=w) { tree[x]+=d; x+=lowbit(x); } } ll query(int x) { ll re=0; while(x>0) { re+=tree[x]; x-=lowbit(x); } return re; } void cdq(int l,int r) { if(l>=r)return ; int mid=(l+r)/2; cdq(l,mid); cdq(mid+1,r); int t1=l,t2=mid+1,ct=l; while(t2<=r) { while(data[t1].x<=data[t2].x&&t1<=mid) { if(data[t1].id==0) add(data[t1].y,data[t1].ad); cp[ct++]=data[t1++]; } if(data[t2].id!=0)ans[data[t2].ad]+=query(data[t2].y); cp[ct++]=data[t2++]; } for(int i=l; i<t1; i++) if(data[i].id==0) add(data[i].y,-data[i].ad); while(t1<=mid)cp[ct++]=data[t1++]; while(t2<=r)cp[ct++]=data[t2++]; for(int i=l; i<=r; i++) data[i]=cp[i]; } int main() { scanf("%lld%lld",&s,&w); while(1) { scanf("%lld",&op); if(op==1) { data[++cnt].id=0; scanf("%lld%lld%lld",&data[cnt].x,&data[cnt].y,&data[cnt].ad); } else if(op==2) { scanf("%lld%lld%lld%lld",&x[1],&y[1],&x[2],&y[2]); q[++tot]=cnt+1; ans[cnt+4]+=(y[2]-y[1]+1)*(x[2]-x[1]+1)*s; data[++cnt].x=x[1]-1,data[cnt].y=y[1]-1,data[cnt].id=2,data[cnt].ad=cnt; data[++cnt].x=x[1]-1,data[cnt].y=y[2],data[cnt].id=2,data[cnt].ad=cnt; data[++cnt].x=x[2],data[cnt].y=y[1]-1,data[cnt].id=2,data[cnt].ad=cnt; data[++cnt].x=x[2],data[cnt].y=y[2],data[cnt].id=3,data[cnt].ad=cnt; } else break; } cdq(1,cnt); for(int i=1; i<=tot; i++) printf("%lld ",ans[q[i]+3]-ans[q[i]+1]-ans[q[i]+2]+ans[q[i]]); return 0; }