Description
Do you like painting? Little D doesn't like painting, especially messy color paintings. Now Little B is painting. To prevent him from drawing messy painting, Little D asks you to write a program to maintain following operations. The specific format of these operations is as follows.
0 : clear all the points.
1 x y c : add a point which color is $c$ at point $(x,y)$.
2 x y1 y2 : count how many different colors in the square $(1,y1)$ and $(x,y2)$. That is to say, if there is a point $(a,b)$ colored $c$, that $1leq aleq x$ and $y1leq bleq y2$, then the color $c$ should be counted.
3 : exit.
Solution
可以视为三维数点问题
对于每一次询问限制为:修改时间在询问之前,修改横坐标在询问横坐标之前,修改的纵坐标在指定区间
CDQ分治
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; int n,tot,opt; long long ans[150050]; struct Q{ int opt,a,b,c,id; bool operator <(const Q &z)const{return a<z.a;} }que[150050],ql[150050],qr[150050]; struct SGT{ long long val; }tr[4000005]; inline int read(){ int w=0,f=1; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();} while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return w*f; } int calc(long long x){return x?x%2+calc(x>>1):0;} void pushup(int i){tr[i].val=tr[i<<1].val|tr[i<<1|1].val;} void update(int i,int l,int r,int p,int v,int opt){ if(l==r){ if(opt)tr[i].val|=(1ll<<v); else tr[i].val=0; return; } int mid=l+r>>1; if(p<=mid)update(i<<1,l,mid,p,v,opt); else update(i<<1|1,mid+1,r,p,v,opt); pushup(i); } long long query(int i,int l,int r,int L,int R){ if(L<=l&&r<=R)return tr[i].val; int mid=l+r>>1; long long ret=0; if(L<=mid)ret|=query(i<<1,l,mid,L,R); if(R>mid)ret|=query(i<<1|1,mid+1,r,L,R); return ret; } void cdq(int l,int r){ if(l==r)return; int mid=l+r>>1,cntl=0,cntr=0,pos=1; cdq(l,mid),cdq(mid+1,r); for(int i=l;i<=mid;i++)ql[++cntl]=que[i]; for(int i=mid+1;i<=r;i++)qr[++cntr]=que[i]; sort(ql+1,ql+cntl+1),sort(qr+1,qr+cntr+1); for(int i=1;i<=cntr;i++){ if(qr[i].opt==2){ while(pos<=cntl&&ql[pos].a<=qr[i].a){ if(ql[pos].opt==1)update(1,1,1000000,ql[pos].b,ql[pos].c,1); ++pos; } ans[qr[i].id]|=query(1,1,1000000,qr[i].b,qr[i].c); } } for(int i=1;i<pos;i++)update(1,1,1000000,ql[i].b,ql[i].c,0); } int main(){ opt=read(); for(;true;){ for(;true;){ opt=read(); if(opt==1||opt==2)++tot,que[tot]=(Q){opt,read(),read(),read(),tot}; else break; } cdq(1,tot); for(int i=1;i<=tot;i++)if(que[i].opt==2)printf("%d ",calc(ans[i])),ans[i]=0; tot=0; if(opt==3)break; } return 0; }