Physical Education Lessons(【CodeForces】915 E)

【题意】n个点q个询问,对于每一个询问,输入l,r,k,如果k是1,代表[l, r]全变成0, k是2就将[l, r]全变成1。

【题解】一眼看去,肯定是维护区间的线段树,然后连范围都没看到。写完以后发现不对,n是1e9,然后想到离散化处理以后用线段树。解法:将点i与点i+1之间的区间大小赋予点i,即点i的权值为点i与点i+1之间的区间大小。然后就可以随便线段树乱写了。注意数据范围,这里好像超了数组不会RE,会报WA,并且查看数据好像是爆int的感觉。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define LL long long
#define lson ins<<1
#define rson ins<<1|1
#define mid (r+l)/2

using namespace std;

const int Max = 6e5+100;
LL Hash[Max<<1], len;
LL num[Max<<1];
struct Tree {
    int l, r, lazy;
    LL sum;
    void updata(int x) {
        if(x==1)sum = 0;
        else if(x==2){
            LL ls=l-1<0?0:num[l-1];
            sum=num[r]-ls;
        }
        lazy = x;
    }
} tree[Max << 2];
LL Ran[Max];

inline void push_down(int ins) {
    int lazyval = tree[ins].lazy;
    if (lazyval) {
        tree[lson].updata(lazyval);
        tree[rson].updata(lazyval);
        tree[ins].lazy = 0;
    }
}

inline void push_up(int ins) {
    tree[ins].sum = tree[lson].sum + tree[rson].sum;
}

inline void build(int l, int r, int ins) {
    tree[ins].l = l, tree[ins].r = r, tree[ins].sum = tree[ins].lazy = 0;
    if (r == l) {
        tree[ins].sum = Ran[l];
    } else if (r > l) {
        build(l, mid, lson);
        build(mid + 1, r, rson);
        push_up(ins);
    }
}

inline void updata_tree(int ql, int qr, int x, int ins) {
    int l = tree[ins].l, r = tree[ins].r;
    if (ql <= l && r <= qr)tree[ins].updata(x);
    else {
        push_down(ins);
        if (ql <= mid)updata_tree(ql, qr, x, lson);
        if (qr > mid)updata_tree(ql, qr, x, rson);
        push_up(ins);
    }
}
struct node{
    int x, y, k;
}data[Max];
int main() {
    int n, m;
    while (~scanf("%d%d", &n, &m)) {
        for(int a=0; a<m; a++)scanf("%d%d%d", &data[a].x, &data[a].y, &data[a].k);
        for(int a=0; a<m; a++)Hash[len++]=data[a].x, Hash[len++]=data[a].y+1;
        Hash[len++]=1, Hash[len++]=n+1;
        sort(Hash, Hash+len);
        len=unique(Hash, Hash+len)-Hash;
        for(int a=0; a<len-1; a++)Ran[a]=Hash[a+1]-Hash[a];
        for(int a=0; a<len-1; a++)a==0?num[a]=Ran[a]:num[a]=num[a-1]+Ran[a];
        build(0, len-2, 1);
        for(int a=0; a<m; a++){
            int x=lower_bound(Hash, Hash+len, data[a].x)-Hash;
            int y=lower_bound(Hash, Hash+len, data[a].y+1)-Hash;//理解为什么这样离散
            y-=1;
            updata_tree(x, y, data[a].k, 1);
            printf("%lld\n", tree[1].sum);
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值