题目:http://acm.hdu.edu.cn/showproblem.php?pid=5023
题意:区间染色覆盖,初始颜色为2,查询区间有多少种颜色,顺序输出颜色标号。
分析:因为颜色只有1~30这30种,可以用一个int型变量,压缩存储颜色。更新:更新的合法区间就返回,把第一次出现区间只有一种颜色的区间的颜色传给两个孩子节点- -,然后往下递归,用更新好的孩子节点来更新父亲节点。查询:查询到合法区间就返回(其值),把第一次出现区间只有一种颜色的区间的颜色传给两个孩子节点,然后往下递归。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=4000000;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
struct segtree
{
int tree[maxn];
int cnt(int v)
{
int num=0;
while(v)
{
v&=(v-1);
num++;
}
return num;
}
void build(int l,int r,int rt)
{
tree[rt]=(1<<2);
if(l==r)
return ;
int m=(l+r)>>1;
build(lson);
build(rson);
}
void updata(int L,int R,int v,int l,int r,int rt)
{
if(L<=l && r<=R)
{
tree[rt]=1<<(v);
return ;
}
int c=cnt(tree[rt]);
if(c==1)
tree[rt<<1]=tree[rt<<1|1]=tree[rt];
int m=(l+r)>>1;
if(L<=m)
updata(L,R,v,lson);
if(R>m)
updata(L,R,v,rson);
tree[rt]=tree[rt<<1]|tree[rt<<1|1];
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l && r<=R)
return tree[rt];
int m=(l+r)>>1;
int c=cnt(tree[rt]);
if(c==1)
return tree[rt];
else
{
int ans=0;
if(L<=m)
ans|=query(L,R,lson);
if(R>m)
ans|=query(L,R,rson);
return ans;
}
}
void DEBUG(int l,int r,int rt)
{
printf("[%d %d]:%d\n",l,r,tree[rt]);
if(l==r)
return ;
int m=(l+r)>>1;
DEBUG(lson);
DEBUG(rson);
}
}T;
int main()
{
int VISIT,N,x,y,v,i;
char str[20];
int out[50],p;
while(scanf("%d%d",&N,&VISIT))
{
if(N==0 && VISIT==0)
return 0;
T.build(1,N,1);
while(VISIT--)
{
scanf("%s",str);
if(str[0]=='P')
{
scanf("%d%d%d",&x,&y,&v);
T.updata(x,y,v,1,N,1);
// T.DEBUG(1,N,1);
}
else
{
int ans=0,p=0;
scanf("%d%d",&x,&y);
ans=T.query(x,y,1,N,1);
for(i=1;i<=30;i++)
{
if(ans&(1<<i))
out[p++]=i;
}
if(p==0)
{
printf("\n");
continue;
}
if(p==1)
printf("%d\n",out[0]);
else
{
for(i=0;i<p-1;i++)
printf("%d ",out[i]);
printf("%d\n",out[i]);
}
// T.DEBUG(1,N,1);
}
}
}
return 0;
}