题意:
有四种操作。
0:清除所有点
1 x y c:给点(x,y)添加一种颜色c
2 x y1 y2:在(0,y1)与(x,y2)所围成的矩形里有多少种颜色
3:程序结束
分析:
注意这里一个点可以有很多种颜色,是不会被覆盖的。
颜色最多51种。我们就建51棵线段树。
每个线段树按y轴建树,每个结点的值是在范围内的最小的x值
/*
建立50颗线段树
没颗线段树表示y轴区间所能取到的x坐标的最小值。
*/
#include<bits/stdc++.h>
using namespace std;
int tree[55];
const int maxn=1e6+10;
int tot;
int l[maxn],r[maxn],v[maxn];
void change(int &k,int L,int R,int y,int x){
if(!k){
k=++tot;
v[k]=x;
}
v[k]=min(v[k],x);
if(L==R) return ;
int mid=L+R>>1;
if(y<=mid) change(l[k],L,mid,y,x);
else change(r[k],mid+1,R,y,x);
}
void query(int k,int L,int R,int tl,int tr,int x,bool& flag){
if(flag||!k) return ;
if(tl>R||tr<L) return;
if(tl<=L&&R<=tr){
if(v[k]<=x) flag=1;
return;
}
int mid=L+R>>1;
query(l[k],L,mid,tl,tr,x,flag);
query(r[k],mid+1,R,tl,tr,x,flag);
}
int main(){
int op;
while(scanf("%d",&op)!=EOF){
if(op==3) break;
if(op==0){
memset(tree,0,sizeof tree);
for(int i=1;i<=tot;i++) l[i]=r[i]=0;
tot=0;
}else if(op==1){
int x,y,c;
scanf("%d%d%d",&x,&y,&c);
change(tree[c],1,1e6,y,x);
}else{
int x,y1,y2,ans=0;
scanf("%d%d%d",&x,&y1,&y2);
for(int i=0;i<=50;i++){
bool flag=0;
query(tree[i],1,1e6,y1,y2,x,flag);
if(flag) ans++;
}
printf("%d\n",ans);
}
}
return 0;
}