1. 程式人生 > >線段樹2 POJ2777 Count Color

線段樹2 POJ2777 Count Color

#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;
}