您的位置:首页 > 其它

POJ 2777 Count Color

2015-08-23 00:29 253 查看
题目链接:http://poj.org/problem?id=2777

题意:给出一面长度为len的墙,一开始的颜色是1,进行2种操作,一是将[l,r]涂成颜色p,二是询问[l,r]区间一共有多少种颜色

思路:对区间进行修改和询问,很容易想到用线段树,但是如何保存有多少种颜色呢,因为颜色少于30种(我又看了题解),所以可以用位运算进行状态压缩,剩下的就是线段树普通的区间修改和更新了(写题的时候花式出错,晚上太亢奋了吧……)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100030
using namespace std;

struct Tree
{
int l,r,date;
}tree[maxn*3];

int lazy[maxn*3];

void build(int root,int l,int r)
{
tree[root].l=l;
tree[root].r=r;
if (l==r)
{
tree[root].date=(1<<1);
return;
}
int mid=(l+r)>>1;
build (root<<1,l,mid);
build (root<<1|1,mid+1,r);
tree[root].date=tree[root<<1].date|tree[root<<1|1].date;
}

void update(int root,int l,int r,int val)
{

if (tree[root].l>=l && tree[root].r<=r)
{
tree[root].date=(1<<val);
lazy[root]=(1<<val);
return;
}

if (lazy[root]!=0)
{
tree[root<<1].date=tree[root].date;
tree[root<<1|1].date=tree[root].date;
lazy[root<<1]=lazy[root];
lazy[root<<1|1]=lazy[root];
lazy[root]=0;
}
int mid=(tree[root].l+tree[root].r)>>1;

if (l<=mid) update(root<<1,l,r,val);
if (r>mid) update(root<<1|1,l,r,val);
tree[root].date=tree[root<<1].date|tree[root<<1|1].date;
}

int que(int root,int l,int r)
{

if (lazy[root]!=0) return lazy[root];

if (tree[root].l==l && tree[root].r==r)
return tree[root].date;

int mid=(tree[root].l+tree[root].r)>>1;
if (r<=mid) return que(root<<1,l,r);
else if (l>mid) return que(root<<1|1,l,r);
else return que(root<<1,l,mid)|que(root<<1|1,mid+1,r);

}

int main()
{
int len,n,m;
while (scanf("%d%d%d",&len,&n,&m)!=EOF)
{
memset(lazy,0,sizeof(lazy));
build (1,1,len);
for (int i=0;i<m;i++)
{
char tem;
cin>>tem;
if (tem=='C')
{
int a,b,p;
scanf("%d%d%d",&a,&b,&p);
if (a>b) swap(a,b);
update(1,a,b,p);
}
else
{
int a,b,res=0,cl;
scanf("%d%d",&a,&b);
if (a>b) swap(a,b);
cl=que(1,a,b);
//  cout<<":"<<cl<<endl;
for (int i=1;i<=n;i++)
{
if ((cl&(1<<i))!=0) res++;
}
printf("%d\n",res);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: