POJ2777 线段树区间染色问题
题意:给L长度的木板,给T种颜色,给O个操作,每次可以选择一段区间染色,或查询一个区间的颜色种类
思路1:用叶节点存具体颜色,父节点记录子节点的颜色集合(都采用二进制从低位到高位表示具体颜色数字)
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int l,t,o;
struct note
{
int left,right,sum,lazy;
void up(int val)
{
sum=1<<(val-1);
lazy=val;
}
} tree[maxn*4];
void pushup(int id)
{
tree[id].sum=tree[id<<1].sum|tree[id<<1|1].sum;
}
void pushdown(int id)
{
if(tree[id].lazy)
{
tree[id<<1].up(tree[id].lazy);
tree[id<<1|1].up(tree[id].lazy);
tree[id].lazy=0;
}
}
void build(int id,int l,int r)
{
tree[id].left=l;
tree[id].right=r;
if(l==r)
tree[id].sum=1;
else
{
int mid=(l+r)/2;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
}
int query(int id,int l,int r)
{
if(l<=tree[id].left&&tree[id].right<=r)
return tree[id].sum;
pushdown(id);
int mid=(tree[id].left+tree[id].right)/2;
int ans=0;
if(l<=mid) ans|=query(id<<1,l,r);
if(r>mid) ans|=query(id<<1|1,l,r);
return ans;
}
void update(int id,int l,int r,int val)
{
if(l<=tree[id].left&&tree[id].right<=r)
{
tree[id].up(val);
return;
}
pushdown(id);
int mid=(tree[id].left+tree[id].right)/2;
if(l<=mid) update(id<<1,l,r,val);
if(r>mid) update(id<<1|1,l,r,val);
pushup(id);
}
int main()
{
int l,t,o;
scanf("%d%d%d",&l,&t,&o);
build(1,1,l);
for(int i=1; i<=o; i++)
{
getchar();
char op;
scanf("%c",&op);
if(op=='C')
{
int l,r,val;
if(l>r)
swap(l,r);
scanf("%d%d%d",&l,&r,&val);
update(1,l,r,val);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
if(l>r)
swap(l,r);
int sum=query(1,l,r);
int ans=0;
while(sum>0)
{
if(sum&1) ans++;
sum=sum>>1;
}
printf("%d\n",ans);
}
}
}
思路2:用线段树叶节点记录颜色所代表的数字,父节点为-1表示两个子节点颜色不相同,>0时的数字代表子节点全为这个数字对应颜色。
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
int a[maxn];
int l,t,o;
int vis[35];
struct note
{
int left,right,sum,lazy;
void up(int val)
{
sum=val;
lazy=val;
}
} tree[maxn*4];
void pushup(int id)
{
if(tree[id<<1].sum==-1||tree[id<<1|1].sum==-1)
tree[id].sum=-1;
else if(tree[id<<1].sum==tree[id<<1|1].sum)
tree[id].sum=tree[id<<1].sum;
else
tree[id].sum=-1;
}
void pushdown(int id)
{
if(tree[id].lazy)
{
tree[id<<1].up(tree[id].lazy);
tree[id<<1|1].up(tree[id].lazy);
tree[id].lazy=0;
}
}
void build(int id,int l,int r)
{
tree[id].left=l;
tree[id].right=r;
if(l==r)
tree[id].sum=1;
else
{
int mid=(l+r)/2;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
}
void query(int id,int l,int r)
{
if(tree[id].sum!=-1)
{
vis[tree[id].sum]=1;
return;
}
// pushdown(id);
int mid=(tree[id].left+tree[id].right)/2;
if(l<=mid) query(id<<1,l,r);
if(r>mid) query(id<<1|1,l,r);
}
void update(int id,int l,int r,int val)
{
if(l<=tree[id].left&&tree[id].right<=r)
{
tree[id].up(val);
return;
}
pushdown(id);
int mid=(tree[id].left+tree[id].right)/2;
if(l<=mid) update(id<<1,l,r,val);
if(r>mid) update(id<<1|1,l,r,val);
pushup(id);
}
int main()
{
scanf("%d%d%d",&l,&t,&o);
build(1,1,l);
for(int i=1; i<=o; i++)
{
char op;
getchar();
scanf("%c",&op);
if(op=='C')
{
int l,r,color;
scanf("%d%d%d",&l,&r,&color);
update(1,l,r,color);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
memset(vis,0,sizeof(vis));
query(1,l,r);
int ans=0;
for(int i=1; i<=30; i++)
{
if(vis[i])
ans++;
}
printf("%d\n",ans);
}
}
}