题意:在一个二维坐标系中,每次有两个操作:
①向一个点加入一种颜色。
①向一个点加入一种颜色。
②询问矩形区域[1,y1],[x,y2]范围内的不同颜色的数量。
题解:KDtree中64位sum记录每个节点的不用颜色的情况,或操作统计答案。
AC代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
const int mxn=350010;
struct node
{
int l,r;
int min[2],max[2];
int d[2];
LL w;
LL sum;
}t[mxn];
int root=0,nowD;
int cmp(const node a,const node b)
{
return a.d[nowD]<b.d[nowD];
}
int cnt;
int lim=0;
inline void pushup(int rt,int x)
{
t[rt].max[0]=max(t[rt].max[0],t[x].max[0]);
t[rt].max[1]=max(t[rt].max[1],t[x].max[1]);
t[rt].min[0]=min(t[rt].min[0],t[x].min[0]);
t[rt].min[1]=min(t[rt].min[1],t[x].min[1]);
return;
}
inline bool in(int x1,int y1,int x2,int y2,int k)
{
return (x1<=t[k].min[0]&&t[k].max[0]<=x2&&y1<=t[k].min[1]&&t[k].max[1]<=y2);
}
inline bool out(int x1,int y1,int x2,int y2,int k)
{
return (x1>t[k].max[0]||x2<t[k].min[0]||y1>t[k].max[1]||y2<t[k].min[1]);
}
int Build(int l,int r,int D)
{
if(l>r)return 0;
nowD=D;int mid=(l+r)>>1;
nth_element(t+l,t+mid,t+r+1,cmp);///
t[mid].max[0]=t[mid].min[0]=t[mid].d[0];
t[mid].max[1]=t[mid].min[1]=t[mid].d[1];
t[mid].sum=t[mid].w;
//
t[mid].l=Build(l,mid-1,D^1);
if(t[mid].l)pushup(mid,t[mid].l);
t[mid].r=Build(mid+1,r,D^1);
if(t[mid].r)pushup(mid,t[mid].r);
//
t[mid].sum=t[mid].w|t[t[mid].l].sum|t[t[mid].r].sum;
return mid;
}
void insert(int &now,int x,int D)
{
if(!now){now=x;return;}
if(t[x].d[D]==t[now].d[D] && t[x].d[!D]==t[now].d[!D])
{
t[now].w|=t[x].w;
t[now].sum|=t[x].w;
--cnt;
return;
}
if(t[x].d[D]<t[now].d[D])
{
insert(t[now].l,x,D^1);
pushup(now,t[now].l);
}
else
{
insert(t[now].r,x,D^1);
pushup(now,t[now].r);
}
t[now].sum=t[now].w|t[t[now].l].sum|t[t[now].r].sum;
return;
}
LL query(int rt,int x1,int y1,int x2,int y2)
{
if(!rt)return 0;
LL res=0;
if(in(x1,y1,x2,y2,rt)){return t[rt].sum;}
if(out(x1,y1,x2,y2,rt)){return 0;}
if(x1<=t[rt].d[0]&&t[rt].d[0]<=x2&&y1<=t[rt].d[1]&&t[rt].d[1]<=y2)res|=t[rt].w;
res|=query(t[rt].l,x1,y1,x2,y2)|query(t[rt].r,x1,y1,x2,y2);
return res;
}
int main()
{
int i,j,op,x,y,w;
lim=9000;
LL lans=0;int X1,X2,Y1,Y2;
while(1)
{
scanf("%d",&op);
if(op==3)break;
if(op==1)
{
cnt++;scanf("%d%d",&t[cnt].d[0],&t[cnt].d[1]);
LL ww;
scanf("%lld",&ww);
t[cnt].w=(1LL<<ww);t[cnt].sum=t[cnt].w;
t[cnt].max[0]=t[cnt].min[0]=t[cnt].d[0];
t[cnt].max[1]=t[cnt].min[1]=t[cnt].d[1];
insert(root,cnt,0);
if(cnt==lim)
{
lim+=9000;
root=Build(1,cnt,0);
}
}
else if(op==2)
{
X1=1;scanf("%d%d%d",&X2,&Y1,&Y2);
lans=query(root,X1,Y1,X2,Y2);
int ans=0;
for(LL i=0;i<51;i++)
if(lans&(1LL<<i))
ans++;
printf("%d\n",ans);
}
else cnt=0,lim=9000,root=0,memset(t,0,sizeof(t));
}
}