线段树2 POJ2777 Count Color

http://poj.org/problem?id=2777

#include <stdio.h>
#include <memory.h>


#define LCH(a) ((a)<<1)
#define RCH(a) (((a)<<1)+1)
#define NO_COLOR 0

typedef struct nodetag{int st, ed, value;} node;

node valtree[400000];
int l,t,o;

void init(int place, int st, int ed)
{
    int mid = (st + ed)/2;
    valtree[place].st = st;
    valtree[place].ed = ed;
    valtree[place].value = 1;
    if(st < ed){
        init(LCH(place), st, mid);
        init(RCH(place), mid+1, ed);
    }
}

void change (int place, int st, int ed, int color)
{
    int mid = (valtree[place].st + valtree[place].ed)/2;
    if(valtree[place].st == st && valtree[place].ed == ed){valtree[place].value = color;}
    else{
        if(valtree[place].value != NO_COLOR)// 假使color == valtree[place].value如何?
        {
            change(LCH(place), valtree[place].st, mid, valtree[place].value);
            change(RCH(place), mid+1, valtree[place].ed, valtree[place].value);
        }
        valtree[place].value = NO_COLOR;
        if(mid + 1 <= st) change(RCH(place), st, ed, color);
        else if(ed <= mid) change(LCH(place), st, ed, color);
        else{
            change(LCH(place), st, mid, color);
            change(RCH(place), mid+1, ed, color);
        }
    }
} 
/*
 change 逻辑是有问题的。没有保持循环不变量。
 假使row3: else color == valtree[place].value, 。。。I
 虽然左右子树的根结点被涂成父结点颜色,且仅迭代一次就因为row2 线段重合返回,
 但是此时父结点被涂成了无色,事实上其应该还是color颜色。所幸通过view计数时,父结点虽然没计数,但是会通过左右儿子结点弥补。
 当I不成立时,没有问题,逻辑同change2
 e.gchange(1,2,2,color),查找这个叶子结点的一路上都会被标记成NO_COLOR
 */
void change2(int place ,int st, int ed, int color)
{
    if(valtree[place].value == color) return;
    int mid = (valtree[place].st + valtree[place].ed) / 2;
    if(valtree[place].st == st && valtree[place].ed == ed) valtree[place].value = color;
    else{
        if(valtree[place].value != NO_COLOR)
        {
            valtree[LCH(place)].value = valtree[place].value;
            valtree[RCH(place)].value = valtree[place].value;
            valtree[place].value = NO_COLOR;
        }
        if(mid+1<=st) change(RCH(place), st, ed, color);
        else if(ed <= mid) change(LCH(place), st, ed, color);
        else {
            change(LCH(place), st, mid, color);
            change(RCH(place), mid+1, ed, color);
        }
    }
}
int ans;
char color[40];

void newcolor(int a)
{
    if(!color[a]){
        color[a] = 1;
        ans++;
    }
}

void view(int place, int st, int ed)//supports st > ed
{
    int mid = (valtree[place].st + valtree[place].ed)/2;
    if(valtree[place].value != NO_COLOR){newcolor(valtree[place].value);}
    else{
        if(ed <= mid) view(LCH(place), st, ed);
        else if(st >= mid+1) view(RCH(place), st, ed);
        else {
            view(LCH(place), st, mid);
            view(RCH(place), mid+1, ed);
        }
    }
}
void view2(int place, int st, int ed) // must st <= ed  不如view好
{
    int mid = (valtree[place].st + valtree[place].ed) / 2;
    if(valtree[place].value != NO_COLOR) newcolor(valtree[place].value);
    else if(ed >= st){
        if(ed <= mid) view(LCH(place), st, ed);
        else if(st >= mid+1) view(RCH(place), st, ed);
        else{
            view(LCH(place), st, mid);
            view(RCH(place), mid+1, ed);
        }
    }
}
/*
 2 2 4
 C 1 1 2
 P 1 2
 C 2 2 2
 P 1 2
 
 */
void exchange(int &a, int &b){ int tmp = a; a = b; b = a;}
int main()
{
    int i, a,b,c;
    char op[2];
    scanf("%d%d%d", &l, &t, &o);
    init(1, 1, l);
    for(i = 0; i < o; ++i)
    {
        scanf("%s", op);
        if(op[0] == 'C'){
            scanf("%d%d%d", &a, &b, &c);
            if(a > b) exchange(a, b);
            change2(1, a, b, c);
        }else if(op[0] == 'P'){
            scanf("%d%d", &a, &b);
            ans = 0; memset(color, 0, sizeof(color));
            view(1, a, b);
            //if(a>b) exchange(a, b);
            //view2(1, a, b);
            printf("%d\n", ans);
        }
    }
    return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值