poj2777(线段树+lazy+位运算)本文讲清楚笔者的思路过程

分析:常规思想的一个个数据更新,会超时,更新速度问题可以想到线段树。而如果用最普通的线段树一样会超时,而由此我们可以用到线段树里面的lazy思想。线段树区间更新,可以不用更新到子节点(因为以后可能用不到,如果下次需要用,则下次把这一次的更新,这就体现了lazy的思想)。此题的颜色,我们可以用位运算来实现,每一位的是否为1,表明有多少颜色。采用lazy标记,更新到满足条件的区间,如果下一次有用到该区间下的子区间,通过lazy标记来更新出上次更新的结果。lazy的标记多种多样,而此题的cover就是其中一种,具体的内容读者自行体会

 

#include <iostream>

#include<stdio.h>

using namespace std;

const int MAX=100010;

int color;

typedef struct no

{

    int left,right;

    int color;

    bool cover;

};

no node[4*MAX];

void Swap(int &a,int &b)

{

    if(a>b)

    {

        int t=a;

        a=b;

        b=t;

    }

}

void build(int l,int r,int id)

{

    node[id].left=l;

    node[id].right=r;

    node[id].color=1;

    node[id].cover=false;

    if(l==r)

        return;

    int mid=(l+r)/2;

    int cur1=id*2;

    int cur2=id*2+1;

    build(l,mid,cur1);

    build(mid+1,r,cur2);

}

void update(int id,int a,int b,int c)

{

    if(node[id].left==a&&node[id].right==b)

    {

        node[id].cover=true;

        node[id].color=1<<(c-1);        

 return;

    }

    if(node[id].cover==true)

    {

        int cur1=id*2,cur2=id*2+1;

        node[cur1].color=node[id].color;

        node[cur1].cover=true;

        node[cur2].color=node[id].color;

        node[cur2].cover=true;

        node[id].cover=false;

    }

    int mid=(node[id].left+node[id].right)/2;

    if(mid>=b)

        update(id*2,a,b,c);

    else

        if(mid<a)

            update(id*2+1,a,b,c);

        else

        {

            update(id*2,a,mid,c);

            update(id*2+1,mid+1,b,c);

        }

        node[id].color=node[id*2].color|node[id*2+1].color;

}

void query(int id,int a,int b,int &ans)

{

    if(node[id].cover||(node[id].left==a&&node[id].right==b))

    {

        ans|=node[id].color;

        return ;

    }

    int mid=(node[id].left+node[id].right)/2;

    if(mid<a)//搜索右子树

        query(id*2+1,a,b,ans);

    else

        if(mid>=b)//搜索左子树

        query(id*2,a,b,ans);

    else

    {

        query(id*2,a,mid,ans);

        query(id*2+1,mid+1,b,ans);

    }

}

int sum(int s)

{

    int ans=0;

    while(s)

    {

        if(s&1)

        ans++;

        s/=2;

    }

    return ans;

}

int main()

{

    int L,T,O;

    scanf("%d%d%d",&L,&T,&O);

    build(1,L,1);

    char ch;

    int a,b,c;

    for(int i=0;i<O;i++)

    {

        cin>>ch;

        if(ch=='C')

        {

            scanf("%d%d%d",&a,&b,&c);

            Swap(a,b);

            update(1,a,b,c);

        }

        else

        {

            color=0;

            scanf("%d%d",&a,&b);

            Swap(a,b);

            int ans=0;

            query(1,a,b,ans);

            printf("%d\n",sum(ans));

        }

    }

    return 0;

}

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值