题目链接:http://poj.org/problem?id=2777
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 40402 | Accepted: 12186 |
Description
Input
Output
Sample Input
2 2 4 C 1 1 2 P 1 2 C 2 2 2 P 1 2
Sample Output
2 1
Source
题目大意:一个长度为L的区间,最多有T种颜色,并且有O种操作,接下去有o行。
一共就两种操作:1、C a b c:表示的是将【a,b】这个区间染成颜色c。 2、P a b :表示的是询问【a,b】这个区间有多少种颜色。
解题思路:这个题目需要注意的是不能一直更新到最下面,就更新到符合的区间即可,否则会超时。
详见代码。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
struct node
{
int l,r;
int num;
} s[400010];
int vis[35];
void InitTree(int l,int r,int k)
{
s[k].l=l;
s[k].r=r;
s[k].num=1;
int mid=(l+r)/2;
if (l==r)
return ;
InitTree(l,mid,2*k);
InitTree(mid+1,r,2*k+1);
}
void UpdataTree(int l,int r,int c,int k)
{
if(s[k].l==l&&s[k].r==r)
{
s[k].num=c;
return;
}
if (s[k].num==c)
return;
if (s[k].num!=-1)//如果所查询的区间不是多种颜色
{
s[2*k].num=s[k].num;//更新区间的颜色
s[2*k+1].num=s[k].num;
s[k].num=-1;//-1表示该区间有多种颜色
}
int mid=(s[k].l+s[k].r)/2;
if (l>mid)
UpdataTree(l,r,c,2*k+1);
else if (r<=mid)
UpdataTree(l,r,c,2*k);
else
{
UpdataTree(l,mid,c,2*k);
UpdataTree(mid+1,r,c,2*k+1);
}
}
void SearchTree(int l,int r,int k)
{
if (s[k].num!=-1)
{
vis[s[k].num]=1;
return;
}
int mid=(s[k].l+s[k].r)/2;
if (r<=mid)
SearchTree(l,r,2*k);
else if (l>mid)
SearchTree(l,r,2*k+1);
else
{
SearchTree(l,mid,2*k);
SearchTree(mid+1,r,2*k+1);
}
}
int main()
{
int l,t,o,ans;
while (~scanf("%d%d%d",&l,&t,&o))
{
InitTree(1,l,1);
while (o--)
{
char ch;
int a,b,c;
getchar();
scanf("%c",&ch);
if (ch=='C')
{
scanf("%d%d%d",&a,&b,&c);
if (a>b)
swap(a,b);
UpdataTree(a,b,c,1);
}
else
{
scanf("%d%d",&a,&b);
if (a>b)
swap(a,b);
memset(vis,0,sizeof(vis));
SearchTree(a,b,1);
ans=0;
for (int i=1; i<=t; i++)
if (vis[i]==1)
ans++;
printf ("%d\n",ans);
}
}
}
return 0;
}
poj 2777 Count Color(线段树+染色问题)
原文:http://blog.csdn.net/qiqi_skystar/article/details/50364489