2017ACM/ICPC广西邀请赛 B Color it

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  1≤a≤x and y1≤b≤y2  then the color c should be counted. 

3: exit. 

Input

The input contains many lines. 

Each line contains a operation. It may be '0', '1 x y c' ( 1≤x,y≤106,0≤c≤50 ), '2 x y1 y2' (1≤x,y1,y2≤106 ) or '3'. 

x,y,c,y1,y2 are all integers. 

Assume the last operation is 3 and it appears only once. 

There are at most 150000 continuous operations of operation 1 and operation 2. 

There are at most 10 operation 0. 
 

Output

For each operation 2, output an integer means the answer . 

Sample Input

0
1 1000000 1000000 50
1 1000000 999999 0
1 1000000 999999 0
1 1000000 1000000 49
2 1000000 1000000 1000000
2 1000000 1 1000000
0
1 1 1 1
2 1 1 2
1 1 2 2
2 1 1 2
1 2 2 2
2 1 1 2
1 2 1 3
2 2 1 2
2 10 1 2
2 10 2 2
0
1 1 1 1
2 1 1 1
1 1 2 1
2 1 1 2
1 2 2 1
2 1 1 2
1 2 1 1
2 2 1 2
2 10 1 2
2 10 2 2
3

Sample Output

2
3
1
2
2
3
3
1
1
1
1
1
1
1

线段树,大体思路:有51种颜色,所以建立51棵线段树,因为横坐标范围是1-x,只要在y1-y2内查询颜色的点横坐标的最小值小于等于x即可,维护区间为y1-y2,维护的值为该区间颜色的x的最小值 。

AC的C++程序如下:

#include<cstdio>
#include<cstring>
#include<string>
#include<cstring>
#include<cmath>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
const int N=1e6+10;
int root[51],cnt=0,fg; //root代表每种颜色的根结点 
int le[4*N],ri[4*N];//存放每个结点的左右子结点 
int Min[4*N];//存放每个结点x的最小值 
inline void init()
{
	memset(root,0,sizeof(root));
	le[0]=0,ri[0]=0,cnt=0,Min[0]=inf;
}
inline void push_up(int rt)
{
	Min[rt]=min(Min[le[rt]],Min[ri[rt]]);
}
inline  void update(int &rt,int l,int r,int L,int val)
{
	if(rt==0)
	{
		rt=++cnt;
		le[rt]=0;
		ri[rt]=0;
		Min[rt]=val;
	}
	if(l==r)
	{
		Min[rt]=min(Min[rt],val);
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid) update(le[rt],l,mid,L,val);
	else update(ri[rt],mid+1,r,L,val);
	push_up(rt);
}
inline void query(int rt,int a,int b,int l,int r,int val)
{
	if(fg||rt==0) return;
	if(a<=l&&b>=r)
	{
		if(Min[rt]<=val) fg=1;
		return;
	}
	int mid=(l+r)>>1;
	if(a<=mid) query(le[rt],a,b,l,mid,val);
	if(b>mid) query(ri[rt],a,b,mid+1,r,val);
}
int main()
{
	int op;
	while(~scanf("%d",&op))
	{
		if(op==3) break;
		if(op==0) init();
		else if(op==1)
		{
			int x,y,c;
			scanf("%d%d%d",&x,&y,&c);
			update(root[c],1,N,y,x);
		}
		else
		{
			int x,y1,y2;
			scanf("%d%d%d",&x,&y1,&y2);
			int ans=0;
			for(int i=0;i<=50;i++)
			{
				fg=0;
				query(root[i],y1,y2,1,N,x);
				ans+=fg;
			}
			printf("%d\n",ans);
		}
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值