내가 넣어 줄 후 플러스 이산 색칠 문제는 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;
}