POJ 2777 Count Color

来源:互联网 发布:mac flash 编辑:程序博客网 时间:2024/05/06 07:41

POJ 2777 Count Color
传送门
题目大意:
给你一个木板,给你一些操作
C A B C
将[A,B]区间涂成颜色C
P A B
查询[A,B]区间有几种颜色
注意!!!
A B的大小不定
A可以大于B
这是坑点
分析:

典型的线段树区间更新加一个col元素col==0时表示区间不是纯色col!=0时表示该区间颜色为col因为col最多只有30种颜色所以开个数组标记一下就可以得到最后的答案了

这里讲一下线段树的区间更新

显然我们可以每次更新到叶子节点,而且这样也是正确的但是面对大量的区间更改每次都更新到叶子节点 耗时会极大的增加于是我们引入了懒惰标记何为懒惰标记即表示当前节点所管辖的线段状态都是一样的那么我们就没必要再向下更新当下次它的子区间需要更新状态时我们将懒惰标记传递给它的子区间//注意理解这句话并取消它本身的懒惰标记这样我们就一直保持记录了所有状态

本题代码如下

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int Max=100005;bool color[35];char s[5];int l,t,o,a,b,c;struct node{  int lson,rson,col;}tree[Max<<2];void build(int l,int r,int n){  tree[n].lson=l;  tree[n].rson=r;  tree[n].col=1;  if(l==r)return;  int mid=(l+r)>>1;  build(l,mid,n<<1);  build(mid+1,r,n<<1|1);}void query(int l,int r,int n){  if(tree[n].col)//col!=0表示tree[n]区间为纯色  {    color[tree[n].col]=true;    return;  }  int mid=(tree[n].lson+tree[n].rson)>>1;  if(l>mid)query(l,r,n<<1|1);  else if(r<=mid)query(l,r,n<<1);  else query(l,mid,n<<1),query(mid+1,r,n<<1|1);}void update(int l,int r,int n,int v){  if(tree[n].lson==l&&tree[n].rson==r)  {    tree[n].col=v;    return;  }  if(tree[n].col)  {    tree[n<<1].col=tree[n<<1|1].col=tree[n].col;    //传递懒惰标记    tree[n].col=0;    //取消自身标记,表示该区间不在是纯色  }  int mid=(tree[n].lson+tree[n].rson)>>1;  if(l>mid)update(l,r,n<<1|1,v);  else if(r<=mid)update(l,r,n<<1,v);  else update(l,mid,n<<1,v),update(mid+1,r,n<<1|1,v);  return;}int getans(){  int ans=0;  for(int i=1;i<=30;i++)    if(color[i])      ans++;//统计答案  memset(color,false,sizeof(color));  return ans;}int main(){  scanf("%d%d%d",&l,&t,&o);  build(1,l,1);  while(o--)  {    scanf("%s%d%d",s,&a,&b);    if(a>b)swap(a,b);    if(s[0]=='C')scanf("%d",&c),update(a,b,1,c);    else query(a,b,1),printf("%d\n",getans());  }  return 0;}
本题还有个加强版本POJ 2528需要对数据离散化处理才能过有兴趣的可以做做
0 0