poj2777 Count Color 线段树区间更新+位操作

来源:互联网 发布:淘宝金牌卖家怎么申请 编辑:程序博客网 时间:2024/05/21 21:47

传送门:poj2777 Count Color

题目大意

有一个长为L的甲板,能把他平均分为L段,每一段能有不同的颜色,为了简便,颜色可以数字(1,2,…T)代表不同的颜色。初始的时候L段均为颜色1。我们能对这个分为L段的甲板做两种操作:
1. C X Y Z,C代表操作 把区间[X,Y]中所有段变为Z颜色
2. P X Y ,P代表操作,表示查询出[X,Y]中有几种不同的颜色

输入:第一行输入三个整数L(甲板的长度),T(颜色的种类),Q(操作的次数)
下面的Q行输入的是操作,遇到查询操作的时候输出
输出:当执行P操作的时候输出该区间不同的颜色种类

解题思路

线段树的区间更新,用到了延时标记。
还有一个就是如何标记不同的颜色,因为每一种颜色的序号都是不同的,所有可以用位运算的方法,1左移颜色的序号减一位,就代表第几号颜色,初始化的时候颜色均为1。然后通过左后孩子颜色进行与运算得到该元素的颜色数量,颜色数量等于这个颜色中1的位数。
最重要的一点就是,这道题中X是可以大于Y的,这里要注意一下

AC代码

#include<cstdio>#include<algorithm>using namespace std;const int MAXN = 200005;typedef long long LL;  //lldLL ans;struct Node{    int left;    int right;    int color;    int addMark;    int mid()    {        return (left+right)>>1;    }}tree[MAXN*4];void pushUp(int rt){    tree[rt].color = ( (tree[rt<<1].color) | (tree[rt<<1|1].color)); //通过左右孩子节点的color得到该节点颜色的数量}void buildTree(int left,int right,int rt){    tree[rt].left = left;    tree[rt].right= right;    tree[rt].addMark = -1;    tree[rt].color = 1;    if(left == right)    {        return ;    }    int mid = tree[rt].mid();    buildTree(left,mid,rt<<1);    buildTree(mid+1,right,rt<<1|1);    pushUp(rt);}void PushDown(int rt){    if(tree[rt].addMark != -1)    {        tree[rt<<1].addMark = tree[rt<<1|1].addMark = tree[rt].addMark;        tree[rt<<1].color = tree[rt<<1|1].color = tree[rt].color;        tree[rt].addMark = -1;    }}void queryTree(int left,int right,int rt,int L,int R){    if(left>=L && right<=R)    {        ans |= tree[rt].color;        return ;    }    PushDown(rt);    int mid = tree[rt].mid();    if(L<=mid)        queryTree(left,mid,rt<<1,L,R);    if(R>mid)        queryTree(mid+1,right,rt<<1|1,L,R);}void updateTree(int left,int right,int rt,int L,int R,int color){    if(left>=L && right<=R)    {        tree[rt].addMark = color;        tree[rt].color = color;        return ;    }    PushDown(rt);    int mid = tree[rt].mid();    if(L<=mid)        updateTree(left,mid,rt<<1,L,R,color);    if(R>mid)        updateTree(mid+1,right,rt<<1|1,L,R,color);    pushUp(rt);}LL tenToLen(LL ans) //计算该数中有多少个1,就代表有几种颜色{    int len = 0;    while(ans)    {        if(ans%2)            len++;        ans/=2;    }    return len;}int main(){    int t,n,o;    int a,b,c;    char ch;    scanf("%d%d%d",&n,&t,&o);    buildTree(1,n,1);    while(o--)    {        getchar();        scanf("%c",&ch);        if(ch == 'C')        {            scanf("%d%d%d",&a,&b,&c);            updateTree(1,n,1,min(a,b),max(a,b),1<<(c-1));//用到了min函数和max保证区间是从大到小        }        else if(ch == 'P')        {            scanf("%d%d",&a,&b);            ans = 0;            queryTree(1,n,1,min(a,b),max(a,b));            printf("%lld\n",tenToLen(ans));        }    }    return 0;}
0 0
原创粉丝点击