POJ2777【线段树】

一直以来就是这么写,很稳。
大晚上先贴个代码吧,下次给加注释。

const int Maxn = 1e5 + 10;

struct Seg{
    int Left, Right;
    int col;
    int _col;
}node[Maxn<<2];

void pushUp(int num){
    node[num].col = node[num<<1].col|node[num<<1|1].col;
}
void pushDown(int num){
    if(node[num]._col){
        node[num<<1].col = node[num<<1|1].col = (1<<node[num]._col);
        node[num<<1]._col = node[num<<1|1]._col = node[num]._col;
        node[num]._col = 0;
    }
}

void Build(int num, int Left, int Right){
    node[num].Left = Left;
    node[num].Right = Right;
    node[num]._col = 0;
    if(Left == Right){
        node[num].col = (1<<1);
        return;
    }
    int Mid = (node[num].Left + node[num].Right) >> 1;
    Build(num<<1, Left, Mid);
    Build(num<<1|1, Mid+1, Right);
    pushUp(num);
}

void update(int num, int s, int t, int col){
    if(node[num].Left >= s && node[num].Right <= t){
        node[num].col = (1<<col);
        node[num]._col = col;
        return;
    }
    pushDown(num);
    int Mid = (node[num].Left + node[num].Right) >> 1;
    if(Mid >= t) update(num<<1, s, t, col);
    else if(Mid < s) update(num<<1|1, s, t, col);
    else{
        update(num<<1, s, Mid, col);
        update(num<<1|1, Mid+1, t, col);
    }
    pushUp(num);
}

int query(int num, int s, int t){
    if(node[num].Left >= s && node[num].Right <= t)
        return node[num].col;
    pushDown(num);
    int Mid = (node[num].Left + node[num].Right) >> 1;
    if(Mid >= t) return query(num<<1, s, t);
    else if(Mid < s) return query(num<<1|1, s, t);
    else{
        int x = query(num<<1, s, Mid);
        int y = query(num<<1|1, Mid+1, t);
        return x|y;
    }
}
int solve(int s, int t, int T){
    int col = query(1, s, t);
    int num = 0;
    for(int i=1;i<=T;i++){
        if(col & (1<<i)) num++;
    }
    return num;
}

int main(){
    char op[5];
    int n, T, q;
    int s, t, col;
    scanf("%d%d%d", &n, &T, &q);
    Build(1, 1, n);
    for(int i=1;i<=q;i++){
        scanf("%s", op);
        if(op[0] == 'C'){
            scanf("%d%d%d", &s, &t, &col);
            if(s > t) swap(s, t);
            update(1, s, t, col);
        }
        else{
            scanf("%d%d", &s, &t);
            if(s > t) swap(s, t);
            printf("%d\n", solve(s, t, T));
        }
    }
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值