poj-2777-线段树

被线段树虐死了。。。

大体题意:

有一块板子,上面的颜色都为1.然后给你以下操作:

C A B C  把A-B染成C

P A B  询问A-B有几种颜色。

做法:

区域更新线段树。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
#define maxn 100010
struct list
{
    int a,b;
    int ct;
    int color;
}node[maxn*4];
int n,t,o;
int ans;
int cnum[31];
void creat(int l,int r,int num)
{
    node[num].a=l;
    node[num].b=r;
    node[num].color=(1<<1);
    node[num].ct=0;
    int mid;
    mid=(l+r)/2;
    if(r-l>=1)
    {
        creat(l,mid,num*2);
        creat(mid+1,r,num*2+1);
    }
}
void insert(int l,int r,int c,int num)
{

    int a=node[num].a;
    int b=node[num].b;
    if(l==a&&r==b)
    {

        node[num].color=cnum[c];
        node[num].ct=c;
        return ;
    }
    int mid=(a+b)/2;
    if(node[num].ct!=0)
    {
        node[num*2  ].ct=node[num].ct;
        node[num*2  ].color=node[num].color;
        node[num*2+1].ct=node[num].ct;
        node[num*2+1].color=node[num].color;
        node[num].ct=0;
    }
    if(mid>=r)
    {
        insert(l,r,c,num*2);
    }
    else if(mid<l)
    {
        insert(l,r,c,num*2+1);
    }
    else
    {
        insert(l,mid,c,num*2);
        insert(mid+1,r,c,num*2+1);
    }
    node[num].color=node[num*2].color|node[num*2+1].color;
}
void search(int l,int r,int num)
{
    int a,b,mid;
    a=node[num].a;
    b=node[num].b;
    mid=(a+b)/2;
    if(l<=node[num].a&&r>=node[num].b)
    {
        ans=ans|node[num].color;
        return ;
    }
    else if((l>=node[num].a&&r<=node[num].b)&&node[num].ct!=0)
    {
        ans=ans|node[num].color;
        return ;
    }
    if(mid>=r)
    {
        search(l,r,num*2);
    }
    else if(mid<l)
    {
        search(l,r,num*2+1);
    }
    else
    {
        search(l,mid,num*2);
        search(mid+1,r,num*2+1);
    }
}
int dos(int x)
{
    int ns=0,i;
    for(i=1;i<=30;i++)
    {
        if((x&(1<<i))!=0)ns++;
    }
    return ns;
}
int main()
{
    int i;
    for(i=1;i<=30;i++)
    {
        cnum[i]=(1<<i);
    }
    while(scanf("%d%d%d",&n,&t,&o)!=EOF)
    {
        creat(1,n,1);
        getchar();
        int a,b,c;
        char ord;
        while(o--)
        {
            scanf("%c",&ord);
            if(ord=='C')
            {
                scanf("%d%d%d%*c",&a,&b,&c);
                if(a>b)swap(a,b);
                insert(a,b,c,1);
            }
            else if(ord=='P')
            {
                scanf("%d%d%*c",&a,&b);
                if(a>b)swap(a,b);
                ans=0;
                search(a,b,1);
                printf("%d\n",dos(ans));
            }
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值