题目链接:http://poj.org/problem?id=2777
题目意思:就是问你在询问的区间里有几种不同的颜色
思路:这题和一般的区间修改差不多,但是唯一不同的就是我们要怎么计算有种颜色,所以这时候我们就需要把延时标记赋予不同的意义,当某段区间有多种颜色时就赋值为-1,当为一种颜色时就把它赋值为这个颜色的号数。这儿我们要怎么统计询问区间不同的颜色数叻,为了不重复计算同一种颜色,那么我们就需要用一个数组来标记计算过的颜色,当我们下次遇到时就不需要再次计算了。。。。
代码核心处就在计数那儿。。。。其它部分都是模板。。。。。。
code:
<span style="font-size:18px;">#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#define L(u) u<<1
#define R(u) u<<1|1
using namespace std;
const int MAXN=100100;
bool vis[35];
int cnt;
struct Node
{
int l,r;
int color;
}node[MAXN*4];
void build(int u,int l,int r) //建树
{
node[u].l=l;
node[u].r=r;
node[u].color=1;
if(l==r)
{
return ;
}
int m=(l+r)/2;
build(L(u),l,m);
build(R(u),m+1,r);
}
void pushdown(int u)
{
if(node[u].color>0)
{
node[L(u)].color=node[R(u)].color=node[u].color;
}
}
void pushup(int u)
{
if(node[L(u)].color==node[R(u)].color)
{
node[u].color=node[L(u)].color;
}
else
{
node[u].color=-1;
}
}
void update(int l,int r,int v,int u)
{
if(l<=node[u].l&&node[u].r<=r)
{
node[u].color=v;
return;
}
pushdown(u);
int m=(node[u].l+node[u].r)/2;
//if(l<=m) update(l,r,v,L(u));
//if(m<r) update(l,r,v,R(u));
if(r<=m) update(l,r,v,L(u));
else if(l>m) update(l,r,v,R(u));
else
{
update(l,m,v,L(u));
update(m+1,r,v,R(u));
}
pushup(u);
}
void query(int l,int r,int u)
{
if(node[u].color>0) //为同一种颜色
{
if(vis[node[u].color]==false) //这种颜色没有计算过
{
cnt++;
}
vis[node[u].color]=true; //标记为计算过的
return ;
}
int m=(node[u].l+node[u].r)/2;
//if(l<=m) query(l,r,L(u));
//if(m<r) query(l,r,R(u));
if(r<=m) query(l,r,L(u));
else if(l>m) query(l,r,R(u));
else
{
query(l,m,L(u));
query(m+1,r,R(u));
}
}
int main()
{
int n,t,q;
while(scanf("%d%d%d",&n,&t,&q)==3)
{
build(1,1,n);
while(q--)
{
char str[10];
scanf("%s",str);
if(str[0]=='C')
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
update(x,y,z,1);
}
else
{
int x,y;
scanf("%d%d",&x,&y);
memset(vis,0,sizeof(vis));
cnt=0;
query(x,y,1);
printf("%d\n",cnt);
}
}
}
return 0;
}
</span>
poj 2777 Count Color(线段树区间修改),布布扣,bubuko.com
原文:http://blog.csdn.net/u010304217/article/details/38276231