题目链接:https://vjudge.net/problem/POJ-2777
题目大意
有一个长度为L的木板,T种颜色,O次操作,每次操作时,‘C’表示涂色,‘P’表示询问区间内有几种不同的颜色。涂色时l,r代表的是l区域到r区域。初始木板颜色为1。
分析
线段树更新以及查询。更新不说了,查询时标记一下该颜色,最后统计1--T内有几种被标记的就ok了。注意,0也会被标记,但是不能算在ans里面。
代码
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N = 100010;
int L,T,O,ans;
bool vis[N];
struct node{
int l,r,val;
}tr[N<<2];
void pushdown(int m)
{
if(tr[m].val)
{
tr[m<<1].val = tr[m].val;
tr[m<<1|1].val = tr[m].val;
tr[m].val = 0;
}
}
void build(int m,int l,int r)
{
tr[m].l = l;
tr[m].r = r;
tr[m].val = 1;
if(l == r) return ;
int mid = (l + r) >> 1;
build(m<<1,l,mid);
build(m<<1|1,mid+1,r);
}
void updata(int m,int l,int r,int val)
{
if(tr[m].val == val) return ;
if(tr[m].l == l && tr[m].r == r)
{
tr[m].val = val;
return ;
}
pushdown(m);
int mid = (tr[m].l + tr[m].r) >> 1;
if(r <= mid)
updata(m<<1,l,r,val);
else if(l > mid)
updata(m<<1|1,l,r,val);
else
{
updata(m<<1,l,mid,val);
updata(m<<1|1,mid+1,r,val);
}
}
void query(int m,int l,int r)
{
if(tr[m].val)
{
vis[tr[m].val] = 1;
return ;
}
pushdown(m);
int mid = (tr[m].l + tr[m].r) >> 1;
if(r <= mid)
query(m<<1,l,r);
else if(l > mid)
query(m<<1|1,l,r);
else
{
query(m<<1,l,r);
query(m<<1|1,l,r);
}
}
int main()
{
while(~scanf("%d%d%d",&L,&T,&O))
{
build(1,1,L);
char s[2];
for(int i=1;i<=O;i++)
{
scanf("%s",s);
if(s[0] == 'C')
{
int l,r,val,tmp;
scanf("%d%d%d",&l,&r,&val);
if(l > r)
{
tmp = l;
l = r;
r = tmp;
}
updata(1,l,r,val);
}
else if(s[0] == 'P')
{
int l,r,tmp;
scanf("%d%d",&l,&r);
if(l > r)
{
tmp = l;
l = r;
r = tmp;
}
memset(vis,0,sizeof vis);
ans = 0;
query(1,l,r);
for(int i=1;i<=T;i++)
if(vis[i]) ans++;
printf("%d\n",ans);
}
}
}
return 0;
}
来源:https://blog.csdn.net/Napom/article/details/98737795