문제를 착색 세그먼트 트리 (예 poj2777입니다)

내가 넣어 줄 후 플러스 이산 색칠 문제는 poj2528이며,


이산 참조 블로그에 대한 자세한 설명 : https://blog.csdn.net/iwts_24/article/details/81603603


스테인드 지역의 커버리지 문제

        대학 문화 측벽을 가정, 각 대학은 상단에 그려진 할 수 있습니다, 높은 요구와 그린 지역은 벽과 동일해야하지만, 어떤 폭 (미터) 정수 여야합니다. 색상을 색칠하는 것은 다른 대학을 커버 할 수있다. 이제이 벽에 그려진 최종 후 여러 대학이 얼마나 많은 색상을 볼 수 있습니다.

        이것은 간단한 색칠 문제입니다. 물론, 여러 버전이 있지만, 대체로이 두 가지 문제는 분리 될 수 없습니다 : 1 개 서비스 지역. 패턴의 얼룩 2. 다양. 이 영역 작업이기 때문에, 다음 세그먼트 트리가 더 합리적이다 사용합니다. 배열 될 수 있지만, 좀 더 큰 규모의 데이터 TLE 것이다.

        물론, 이산 문제를 염색와 블로그의 많은이 두 가지에 의해 작성, 크게 분리되어 있습니다. 그러나 나는 개인적으로 이해 세그먼트 트리에서 문제를 염색하는 것은 그래서 혼자 여기에, (물론, 너무 많은 음식 = 거물은 어려움이 나무의 이산 세그먼트라고 생각합니다) 도움이된다 생각합니다.

기여

        세그먼트 나무는 그것의 본질은 여전히 ​​같은 코드와 같은 일부 그냥, 다양한 형태, 나는 많은 사람들이 쓰는 블로거의 배열로 작성된 구조를 취하고있다 느낌이 걸립니다.

        전반적으로, 우리는 데이터의 조각에 트리 라인을 구축, 그는 간격을 수정 유사 스테인드 지역 인 경우. 세그먼트 트리의 본질은 게으른 배열을 사용하는 것입니다, 우리는 상황이 영역을 얻을 수있는 자식 노드를 통과하지 않도록 할 수 있습니다. 범위의 기간 동안,이 속성을 사용하여도 염색 그래서, 우리는 표현 노드를 위로하고 싶다. 그런 다음 우리는 세 가지 변수를 설정할 수 있습니다 : -1 현재 세그먼트 다양한 색상이 있음을 나타냅니다, 귀찮게하지 않습니다 특히 얼마나 많은. 0은 현재 지역이 염색되지 않은 것을 나타낸다. 현재 단일 얼룩을 나타내는 양의 정수 영역을 염색하고, 색 수는 양의 정수이다.

        그래서 특별한 요구 사항에 추가하여, 우리는 일반적으로 (해시, 또는 이동식 정수를 쓰기 위해, 우리는, INT가 될 수있는 주제 유형의 문자 또는 문자열의 경우에도) 색상을 표현하기 위해 int 형을 사용합니다. 그런 다음에 보면
예 : ----------------


 이것은 상기 요구에 따른 세그먼트 트리에 기록 -1 현재 세그먼트가 다양한 색상을 갖는 것을 나타내고, 현재의 세그먼트가 모두 1로 표현된다. 여기서, 1 0 좌측 및 노드 1 내지 여전히. 우리는 찾을 당신이 바로 그 답을 얻을 수 0 제외하면 0으로 기본도 컬러로, 당신이 진짜 코드를 절약 할 수 있기 때문이다.

        요컨대, 이러한 세그먼트 트리의 설립 염색 영역의 일반적인 상황을 나타낼 수있다. 색상의 정확한 수는 쿼리의 시간에 작동하는 데 필요한.
 

난 그냥 시작한 다음 이산 문제는 염색하지 않기 때문에 그런 변화는 ...이 질문은 나를 위해 레인 어떻게 얼룩을 알고 각 서브 루틴에서 가장 큰 이득 각 로컬 세그먼트 트리 템플릿 변환입니다 아이디어는 어떻게 성과 모르는 ORZ

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define LL long long
const long int maxn=2e5+10;
int a[maxn*4];
int tree[maxn*4];
int color[40];
int lazy[maxn*4];
int n,t,colors;
int ans;
//0 表示没染色,-1表示杂,正整数表示该种的纯色  //本题目要求刚开始全为1 

void Pushup(int rt)
{
	if(tree[rt*2]==tree[rt*2+1])
	{
		tree[rt]=tree[rt*2];		//两个子叶颜色一样说明可能是纯的或者都是-1 
	}
	else
	tree[rt]=-1;  ///-1表示杂的颜色 
}

void Build(int l,int r,int rt)
{
	if(l==r)
	{
		tree[rt]=a[l];return;
	}
	
	int m=(l+r)/2;
	Build(l,m,rt*2);
	Build(m+1,r,rt*2+1);
	
	Pushup(rt);
}

void Pushdown(int rt,int llen,int rlen)  ///这道题不是长度了 
{
	if(lazy[rt]!=0)
	{
		lazy[rt*2]=lazy[rt];
		lazy[rt*2+1]=lazy[rt];
		
		tree[rt*2]=lazy[rt];
		tree[rt*2+1]=lazy[rt];
		
		lazy[rt]=0;
		
	}
}

void Update(int l,int r,int rt,int L,int R,int C)
{
	if(L<=l&&r<=R)
	{
	    tree[rt]=C;
		lazy[rt]=C;
		return;
	}
	int m=(l+r)/2;
	
	Pushdown(rt,m-l+1,r-m);	
	
	if(L<=m) Update(l,m,rt*2,L,R,C);        ////死循环一定是哪里小地方写错了 
	if(m<R)	 Update(m+1,r,rt*2+1,L,R,C);
	Pushup(rt);
	
}
void Query(int l,int r,int rt,int L,int R)
{
	
	if(L<=l&&r<=R)
	  {
		if(tree[rt]==0) return;
		
		else if(tree[rt]==-1)  //杂色继续往下找 
		{
			int m=(l+r)/2;
			///往下走要更新lazy			
			Pushdown(rt,m-l+1,r-m);
			
			if(L<=m)	Query(l,m,rt*2,L,R);
			
			if(m<R)		Query(m+1,r,rt*2+1,L,R);	
		}		
		
		else		//代表正整数的情况 
		{
			if(color[tree[rt]]==0) //该种纯色未被访问过 
			{
				ans++;             ///加一次 
				color[tree[rt]]=1;  ///该种纯色不再加 
			}
		}
	return;			
	}	
	int m=(l+r)/2;
	
	Pushdown(rt,m-l+1,r-m);
	if(L<=m) Query(l,m,rt*2,L,R);
	if(m<R)	 Query(m+1,r,rt*2+1,L,R);		

}
int main(void)
{
	while(scanf("%d%d%d", &n, &colors, &t)!=EOF)
	{
		memset(lazy,0,sizeof(lazy));memset(tree,0,sizeof(tree));
		
	
		int g,h,j;
		for(int i=1;i<=n+1;i++)
		 	a[i]=1;
		 	
		Build(1,n,1);
	
		for(int i=1;i<=t;i++)
		{
			ans=0;memset(color,0,sizeof(color));
			char str[3];
			scanf("%s", str);
			
			int t;
			if(str[0]=='C')
			{
				
				scanf("%d%d%d",&g,&h,&j);
				if(g>h)
				{
					t=g;g=h;h=t;	
				}
				Update(1,n,1,g,h,j);	
			}		
			else if(str[0]=='P')
			{
		        scanf("%d%d",&g,&h);
				if(g>h)
				{
					t=g;g=h;h=t;		
				}
				Query(1,n,1,g,h);		
				printf("%d\n",ans);memset(color,0,sizeof(color));		
		    } 
	    } 	
	}
return 0;	
}

게시 50 개 원래 기사 · 원 찬양 6 · 전망 1746

추천

출처blog.csdn.net/zstuyyyyccccbbbb/article/details/104110637