POJ 2777

  一道线段树的区间修改题,给区间染色,最后输出一个区间的颜色种数,由于颜色不会超过30种,所以可以用int型二进制的每一位表示一种颜色,比如颜色1就是000……0001,颜色3是000……100,那么一个区间内如果有两种颜色A和B,管辖这两个区间的大区间的颜色就为 A|B,最后根据查询到的数得出二进制中1的个数,从而判断出有几种颜色。

  写这道题的时候,swap函数出现了一个错误:

  swap(int *a,int *b)

  int *c

  if(*a>*b) 

    *c=*a;

    *a=*b;

    *b=*a;

  这暴露出我的C语言基础还不扎实,开始声明*c的时候没有赋值,后来又要对这个野指针进行取值,显然是不对的。

#include<stdio.h>
#define MAX_LENGTH 100005
struct node
{
    int left;
    int right;
    int tag;
    int color; 
}board[MAX_LENGTH*4];
void build(int,int,int);
void update(int,int,int,int);
inline void pushdown(int);
inline void pushup(int);
inline void swap(int *,int *);
int query(int,int,int);
inline int calcu(int);
int main()
{
    int l,t,o;
    while(scanf("%d%d%d",&l,&t,&o)!=EOF)
    {
    build(1,1,l);
    int i;
    for(i=0;i<o;i++)
    {
        char ope[2];
        scanf("%s",ope);
        if(ope[0]=='C')
        {
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        c=1<<(c-1);//将颜色的种类体现在二进制的某一位上
        swap(&a,&b);
        update(1,a,b,c);
        }
        else
        {
        int a,b,ans;
        scanf("%d%d",&a,&b);
        swap(&a,&b);
        ans=query(1,a,b);
        ans=calcu(ans);
        printf("%d\n",ans);
        }
    }
    }
    return 0;
}
void build(int root,int le,int ri)
{
    board[root].left=le;
    board[root].right=ri;
    board[root].color=1;
    board[root].tag=0;
    if(le==ri)
    return ;
    int mid=(le+ri)/2;
    build(2*root,le,mid);
    build(2*root+1,mid+1,ri);
}
inline void swap(int *a,int *b)
{
    int c;
    if(*a>*b)
    {
    c=*a;
    *a=*b;
    *b=c;
    }
}
void update(int root,int le,int ri,int val)
{
    if(le<=board[root].left&&ri>=board[root].right)
    {
    board[root].color=val;
    board[root].tag=val;
    return ;
    }
    if(le>board[root].right||ri<board[root].left)
    {
    return ;
    }
    pushdown(root);
    update(2*root,le,ri,val);
    update(2*root+1,le,ri,val);
    pushup(root);
}
inline void pushup(int root)
{
    board[root].color=board[2*root].color|board[2*root+1].color;
}
inline void pushdown(int root)
{
    if(board[root].tag)
    {
    board[root*2].color=board[root].color;
    board[root*2+1].color=board[root].color;
    board[root*2].tag=board[root].tag;
    board[root*2+1].tag=board[root].tag;
    board[root].tag=0;
    }
}
int query(int root,int le,int ri)
{
    if(le<=board[root].left&&ri>=board[root].right)
    {
    return board[root].color;
    }
    if(le>board[root].right||ri<board[root].left)
    {
    return 0;
    }
    pushdown(root);
    pushup(root);
    return query(2*root,le,ri)|query(2*root+1,le,ri);
}
inline int calcu(int x)
{
    int ans=0;
    while(x)
    {
    ans+=x&1;
    x>>=1;
    }
    return ans;
}

转载于:https://www.cnblogs.com/coredux/archive/2012/08/08/2627639.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值