POJ 2777 Count Color(线段树!!!)
http://poj.org/problem?id=2777
题意:给出一段区间 L ,T种颜色,O种操作(1 <= L <= 100000), T(1 <= T <= 30) , (1 <= O <= 100000). ,初始时颜色都是染第一种颜色,然后再修改一些区间的颜色,给出一段区间,问这段区间内有多少种颜色。
1 .线段树的一个很重要的部分就是节点存的内容,除了l,r,c外还有一个state(该段区间有多少种颜色),开始没state还超时了,加了一个剪枝勉强过,可是30种染色,用二进制存的话,效率很高,所以改成了二进制
2. 更新时的下传和上传,very重要
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 100100
using namespace std;
struct Node
{
int l,r,c,state;
}node[nMAX*4];
int L,T;
void create(int l,int r,int u)
{
node[u].l=l,node[u].r=r,node[u].state=1,node[u].c=0;//初始化为0
if(l==r)return ;
int mid=(l+r)/2;
create(l,mid,2*u);
create(mid+1,r,2*u+1);
}
void printColor(int l,int r,int c,int u)
{
if(node[u].l>=l&&node[u].r<=r)
{node[u].c=c; node[u].state=1<<(c-1); return;}
if(node[u].c)//下传
{
node[2*u].c=node[u].c,node[2*u+1].c=node[u].c;
node[2*u].state=node[u].state,
node[2*u+1].state=node[u].state,
node[u].c=0;
}
int mid=(node[u].l+node[u].r)/2;
if(r<=mid) printColor(l,r,c,2*u);
else if(l>mid) printColor(l,r,c,2*u+1);
else
{
printColor(l,mid,c,2*u);
printColor(mid+1,r,c,2*u+1);
}
node[u].state=node[2*u].state|node[2*u+1].state;//上传
}
int calculate(int l,int r,int u)
{
if(node[u].l>=l&&node[u].r<=r)
return node[u].state;
if(node[u].c)//下传
{
node[2*u].c=node[u].c, node[2*u+1].c=node[u].c;
node[2*u].state=node[u].state,
node[2*u+1].state=node[u].state,
node[u].c=0;
}
int mid=(node[u].l+node[u].r)/2;
if(r<=mid) {return calculate(l,r,2*u);}
else if(l>mid) {return calculate(l,r,2*u+1);}
else
return calculate(l,mid,2*u)|calculate(mid+1,r,2*u+1);
}
int Binary(int u)
{
int ans=0;
while(u>0)
{
if(u%2)ans++;
u/=2;
}
return ans;
}
int main()
{
int i,j,k,O;
char ch;
while(~scanf("%d%d%d",&L,&T,&O))
{
create(1,L,1);
int cnt=1;
while(O--)
{
getchar();
scanf("%c",&ch);
if(ch=='C')
{
scanf("%d%d%d",&i,&j,&k);
int t;
if(i>j){t=i,i=j,j=t;}
printColor(i,j,k,1);
}
else
{
scanf("%d%d",&i,&j);
int t;
if(i>j){t=i,i=j,j=t;}
int ans=calculate(i,j,1);
ans=Binary(ans);
printf("%d\n",ans);
}
}
}
return 0;
}

浙公网安备 33010602011771号