poj2777 Count Color

/*
 * poj2777 AC
 * 線段樹基礎
 * 注意:初始狀態時board已經染爲了顏色1
 * 看到顏色只有30種時,果斷想到了用二進制數來保存顏色,一個long足夠了。
 *
 * 線段樹:
 * 	   線段樹的基本操作參考AHYY的線段樹講稿。
 * 	   現在終於注意到了隊結點標記的重要性,即要保持結點的一致性。
 * 	   
 * 	   一致性:
 * 	   	   結點的一致性要求了一個結點在更新過程中必須,染色(或者數據的更新)必須完
 * 	   整覆蓋整個結點區間,否則該結點不能提供正確的信息,而必須繼續查詢其左右子結
 * 	   點,直到一個具有一致性的結點出現。
 * 	       而具有一致性的結點,就將其做上標記,有標記的結點包含的信息就可以包含其
 * 	   子結點的所有信息了。所以查詢中,查詢區間若屬於一個標記結點的子集,則可返回
 * 	   標記結點的值。
 * 	   	   更新線段樹過程,也是一個對標記的更新。
 * 註釋部分爲我原始的程序,即沒有考慮到標記的問題。
 *
 * */
 
#include<stdio.h>
#include<memory.h>
#define MAX 100002
struct NODE
{
	long color;		//二進制數記錄有哪些顏色
	long low,high;
	bool mark;
}tree[MAX*2];
long left[MAX*2],right[MAX*2];
long l,t,o,tot = 0;

void build(long a,long b)
{
	tree[++tot].low = a,tree[tot].high = b;
	if(a==b) return;
	long m = tot;
	left[m] = tot+1,build(a,(a+b)/2);
	right[m] = tot+1,build((a+b)/2+1,b);
	return;
}

void change(long a,long b,long c,long k)
{
	if(a>b || tree[k].low>b || tree[k].high<a) return;
	if(tree[k].low==a && tree[k].high==b)
	{
		tree[k].color = c;
		tree[k].mark =true;
		return;
	}

	if(tree[k].mark)
	{
		tree[right[k]].color = tree[left[k]].color = tree[k].color;
		tree[right[k]].mark = tree[left[k]].mark = true;
		tree[k].mark = false;
	}
/**
	change(a,b,c,left[k]);
	change(a,b,c,right[k]);
	if(tree[k].mark)
	{
		tree[k].mark = false;
		if(a>mid)
		{
			change(a,b,c,right[k]),change(mid+1,a-1,tree[k].color,right[k]),change(b+1,tree[k].high,tree[k].color,right[k]);
			change(tree[k].low,mid,tree[k].color,left[k]);
		}
		else if(b<=mid)
		{
			change(a,b,c,left[k]),change(tree[k].low,a-1,tree[k].color,left[k]),change(b+1,mid,tree[k].color,left[k]);
			change(mid+1,tree[k].high,tree[k].color,right[k]);
		}
		else
		{
			change(tree[k].low,a-1,tree[k].color,left[k]);
			change(a,mid,c,left[k]);
			change(mid+1,b,c,right[k]);
			change(b+1,tree[k].high,tree[k].color,right[k]);
		}
	}else
**/

	long mid = (tree[k].low+tree[k].high)>>1;
	if(a>mid)
		change(a,b,c,right[k]);
	else if(b<=mid)
		change(a,b,c,left[k]);
	else
	{
		change(a,mid,c,left[k]);
		change(mid+1,b,c,right[k]);
	}	

	if(tree[left[k]].mark && tree[right[k]].mark && tree[left[k]].color==tree[right[k]].color) 
		tree[k].color = tree[left[k]].color,tree[k].mark = true;
	return;
}

long quiry(long a,long b,long k)
{
	long ans = 0;
//	if(a>b || tree[k].low>b || tree[k].high<a) return 0;
	if(a>b) return 0;
	if(tree[k].mark && tree[k].low<=a && tree[k].high>=b)
	{
		ans = tree[k].color;
		return ans;
	}
	/*else
	{
		ans = quiry(a,b,left[k])|quiry(a,b,right[k]);
		return ans;
	}*/

	long mid = (tree[k].low+tree[k].high)>>1;
	if(a>mid)
		ans = quiry(a,b,right[k]);
	else if(b<=mid)
		ans = quiry(a,b,left[k]);
	else 
		ans = quiry(a,mid,left[k])|quiry(mid+1,b,right[k]);
	return ans;

}

int main()
{
//	FILE* fin;
//	fin = fopen("d.in","r");
	scanf("%ld%ld%ld",&l,&t,&o);
//	fscanf(fin,"%ld%ld%ld",&l,&t,&o);
	memset(tree,0,sizeof(0));
	memset(left,0,sizeof(left));
	memset(right,0,sizeof(right));
	build(1,l);
	tree[1].mark = true,tree[1].color = 1;
	for(long i=1;i<=o;i++)
	{
		char s[2];
		long a,b,c,t;
		scanf("%s",s);
//		fscanf(fin,"%s",s);
		if(s[0]=='C')
		{
			scanf("%ld%ld%ld",&a,&b,&c);
//			fscanf(fin,"%ld%ld%ld",&a,&b,&c);
			if(a>b) t = a,a = b,b = t;
			change(a,b,(1<<(c-1)),1);
		}else 
		{
			scanf("%ld%ld",&a,&b);
//			fscanf(fin,"%ld%ld",&a,&b);
			if(a>b) c = a,a = b,b = c;
			long ans = 0,v = quiry(a,b,1);
			while(v) v &= (v-1),ans++;	
			
			printf("%ld\n",ans);
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章