标签:cstring style const one 静态 using 前缀和 color oid
CDQ分治不但能解决三维偏序问题,还能将某些问题的动态版本变成静态。
比如这题是单点修改,区间查询,这样我们就可以将输入的顺序当作时间轴,之后进行CDQ分治
按x轴排序后,对y进行树状数组加减,这道题就变成了x比他小,并且y也比他小的个数查询
这题还用到了简单的容斥原理,也就是二维前缀和的思想来求取矩形真正的内容
#include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; typedef long long ll; const int N=2e6+10; const int mod=1e9+7; struct node{ int a,x,y,v,op,id; }q[N]; ll tr[N],ans[N]; int lowbit(int x){ return x&-x; } void add(int x,int c){ int i; for(i=x;i<=N;i+=lowbit(i)){ tr[i]+=c; } } ll sum(int x){ ll res=0; int i; for(i=x;i;i-=lowbit(i)){ res+=tr[i]; } return res; } bool cmpb(node a,node b){ if(a.x==b.x) return a.op<b.op; return a.x<b.x; } void cdq(int l,int r){ if(l==r) return ; int mid=l+r>>1; cdq(l,mid); cdq(mid+1,r); sort(q+l,q+1+r,cmpb); int i; for(i=l;i<=r;i++){ int id=q[i].id; if(q[i].op==1&&q[i].a<=mid) add(q[i].y,q[i].v); if(q[i].op==2&&q[i].a>=mid+1) ans[id]+=sum(q[i].y); if(q[i].op==3&&q[i].a>=mid+1) ans[id]-=sum(q[i].y); } for(i=l;i<=r;i++){ if(q[i].op==1&&q[i].a<=mid) add(q[i].y,-q[i].v); } } int main(){ int n,w; cin>>n>>w; int cnt=0; int idx=0; while(cin>>n&&n!=3){ if(n==1){ int x,y,c; scanf("%d%d%d",&x,&y,&c); cnt++; q[cnt]=node{cnt,x,y,c,1}; } if(n==2){ int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); cnt++; idx++; q[cnt]=node{cnt,x2,y2,0,2,idx}; ++cnt; q[cnt]=node{cnt,x1-1,y1-1,0,2,idx}; ++cnt; q[cnt]=node{cnt,x2,y1-1,0,3,idx}; ++cnt; q[cnt]=node{cnt,x1-1,y2,0,3,idx}; } } cdq(1,cnt); for(int i=1;i<=idx;i++){ cout<<ans[i]<<endl; } }
标签:cstring style const one 静态 using 前缀和 color oid
原文地址:https://www.cnblogs.com/ctyakwf/p/12751161.html