题目:
http://poj.org/problem?id=2777题意:
一个长L的木板,一开始颜色是1,不断的重新刷新其中一段的颜色,并且随时询问某一区间内的颜色数目。思路:
颜色最多30种,所以可以用一个int按位表示,在线段树上跑,转移就是儿子节点的颜色按位或,理解线段树之后还是很简单的。
代码:
//kopyh
#include <bits/stdc++.h>
#define N 1123456
using namespace std;
int n,m,res,flag;
#define root 1 , n , 1
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
int sum[N<<2],add[N<<2];
void pushUp(int rt)
{
sum[rt] = sum[rt<<1]|sum[rt<<1|1];
}
void pushDown(int l,int r,int rt)
{
if(add[rt])
{
int m = (l+r)>>1;
sum[rt<<1] = sum[rt<<1|1] = add[rt];
add[rt<<1] = add[rt<<1|1] = add[rt];
add[rt] = 0;
}
}
void update(int l,int r,int rt,int ql,int qr,int val)
{
if(l>qr||ql>r)return;
if(l>=ql&&r<=qr)
{
sum[rt] = val;
add[rt] = val;
return;
}
pushDown(l,r,rt);
int m = (l+r)>>1;
if(ql<=m)update(lson,ql,qr,val);
if(qr>m)update(rson,ql,qr,val);
pushUp(rt);
}
void build(int l,int r,int rt)
{
add[rt]=0;
if(l == r)
{
sum[rt]=res;
return;
}
int m = (l+r)>>1;
build(lson);
build(rson);
pushUp(rt);
}
int query(int l,int r,int rt,int ql,int qr)
{
if(l>qr||ql>r)
return 0;
if(l>=ql&&r<=qr)
return sum[rt];
pushDown(l,r,rt);
int m = l+r>>1;
return query(l,m,rt<<1,ql,qr)|query(m+1,r,rt<<1|1,ql,qr);
}
int solve(int pos)
{
int t=0;
while(pos)
t+=(pos&1),pos>>=1;
return t;
}
int main()
{
int i,j,k,cas,T,t,x,y,z;
char s[10];
while(scanf("%d%d%d",&n,&T,&m)!=EOF)
{
res=(1<<1);
build(root);
for(i=0;i<m;i++)
{
scanf("%s",s);
if(s[0]=='C')
{
scanf("%d%d%d",&x,&y,&z);
if(x>y)x^=y,y^=x,x^=y;
res=0;
update(root,x,y,1<<z);
}
else
{
scanf("%d%d",&x,&y);
if(x>y)x^=y,y^=x,x^=y;
printf("%d\n",solve(query(root,x,y)));
}
}
}
return 0;
}