Hdu-6183 Color it(cdq分治)

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 1ax and y1by2, 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' ( 1x,y106,0c50 ), '2 x y1 y2' ( 1x,y1,y2106 ) 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 10operation 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


分析:颜色只有50个,可以考虑用一个long long来表示,:这题的查询操作很特殊,每次查询的是一个紧贴着y轴的矩阵中的颜色数,所以我们只需要用线段树维护纵轴方向的颜色集合,那么每次查询就是横轴上的一个前缀和,修改操作只要用cdq分治对时间进行分治就把修改时间这一维忽略了,剩下的就是按横标从左到右动态插入和查询答案,直接用动态开点线段树解决,总复杂度n*logn(线段树)*logn(cdq对时间的分治)。


#include 
using namespace std;
const int N = 2e6;
typedef long long ll;
inline int read()
{
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}   
class thing
{
	public:
	int op,x,y,z,t,lab;
	friend bool operator < (const thing &a,const thing &b)
	{
		if(a.x != b.x) return a.x < b.x;
		return a.t < b.t;
	}
}job[N],work[N],tmp[N];
int n,num,cnt,root,tot,ch[N*2][2];
ll ans[N],mask[N*2];
int Count(ll x)
{
	int cnt = 0;
	while(x)
	{
		cnt++;
		x -= x & (-x);
	}
	return cnt;
}
void Insert(int &u,int l,int r,int x,int val)
{
	if(!u) u = ++cnt;
	mask[u] |= 1ll<>1;
	if(x <= mid) Insert(ch[u][0],l,mid,x,val);
	else Insert(ch[u][1],mid+1,r,x,val);
}
ll Query(int u,int l,int r,int x,int y)
{
	if(!u) return 0;
	if(l == x && r == y) return mask[u];
	int mid = (l+r)>>1;
	if(y <= mid) return Query(ch[u][0],l,mid,x,y);
	else 
	 if(x <= mid) return Query(ch[u][0],l,mid,x,mid) | Query(ch[u][1],mid+1,r,mid+1,y);
	 else return Query(ch[u][1],mid+1,r,x,y);
}
void Del(int &u)
{
	if(!u) return;
	Del(ch[u][0]);
	Del(ch[u][1]);
	mask[u] = 0;
	u = 0;
}
void cdq(int l,int r)
{
	if(l >= r) return;
	int mid = (l+r)>>1;
	for(int i = l;i <= r;i++)
	 if(work[i].op == 1 && work[i].t <= mid) Insert(root,1,1e6,work[i].y,work[i].z);
	 else 
	  if(work[i].op == 2 && work[i].t > mid) ans[work[i].lab] |= Query(root,1,1e6,work[i].y,work[i].z);
	Del(root);
	cnt = 0;
	int l1 = l-1,r1 = mid;
	for(int i = l;i <= r;i++)
	 if(work[i].t <= mid) tmp[++l1] = work[i];
	 else tmp[++r1] = work[i];
	for(int i = l;i <= r;i++) work[i] = tmp[i]; 
	cdq(l,mid);
	cdq(mid+1,r);
}
void deal(int l,int r)
{
	if(l > r) return;
	n = r - l + 1;
	num = 0;
	for(int i = l;i <= r;i++) 
	 if(job[i].op == 2) job[i].lab = ++num;
	for(int i = l;i <= r;i++) 
	{
		work[i-l+1] = job[i];
		work[i-l+1].t = i-l+1;
	}
	sort(work+1,work+1+n);
	cdq(1,n);
	for(int i = 1;i <= num;i++) 
	{
		cout<


你可能感兴趣的:(不会做,好题,分治算法,离线算法,ACM)