【LOJ】#2037. 「SHOI2015」脑洞治疗仪

题解

维护区间内1的个数,左边数0的长度,右边数0的长度,区间内0区间最长个数,覆盖标记
第一种操作区间覆盖0
第二种操作查询\([l_0,r_0]\)中1的个数,区间覆盖0,然后覆盖时找到相对应的区间时对于如果1够把这个区间覆盖掉的话就直接cover,否则就递归该区间,如果能覆盖左区间就覆盖去右区间否则就覆盖左区间
第三种操作直接查询左右区间特判跨越中间

代码

#include <bits/stdc++.h>
#define enter putchar('\n')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 200005
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int N,M;
struct node {
    int l,r,ll,rl,cov,cnt,v;
}tr[MAXN * 4];
void cover(int u,int v) {
    int len = tr[u].r - tr[u].l + 1;
    tr[u].cov = v;
    if(!v) {tr[u].ll = len;tr[u].rl = len;tr[u].v = len;tr[u].cnt = 0;}
    else {tr[u].ll = 0;tr[u].rl = 0;tr[u].v = 0;tr[u].cnt = len;}
}
void update(int u) {
    tr[u].v = max(tr[u << 1].v,tr[u << 1 | 1].v);
    tr[u].v = max(tr[u << 1].rl + tr[u << 1 | 1].ll,tr[u].v);
    tr[u].cnt = tr[u << 1].cnt + tr[u << 1 | 1].cnt;
    tr[u].ll = (!tr[u << 1].cnt) ? tr[u << 1].r - tr[u << 1].l + 1 + tr[u << 1 | 1].ll : tr[u << 1].ll;
    tr[u].rl = (!tr[u << 1 | 1].cnt) ? tr[u << 1 | 1].r - tr[u << 1 | 1].l + 1 + tr[u << 1].rl : tr[u << 1 | 1].rl;
}
void push_down(int u) {
    if(tr[u].cov != -1) {
        cover(u << 1,tr[u].cov);
        cover(u << 1 | 1,tr[u].cov);
        tr[u].cov = -1;
    }
}
void build(int u,int l,int r) {
    tr[u].l = l;tr[u].r = r;tr[u].cov = -1;
    if(l == r) {
        cover(u,1);
        return;
    }
    int mid = (l + r) >> 1;
    build(u << 1,l,mid);
    build(u << 1 | 1,mid + 1,r);
    update(u);
}

int cmp(int a,int b,int on) {
    if(!on) return a + b;
    else return max(a,b);
}
int Query(int u,int l,int r,int on) {
    if(tr[u].l == l && tr[u].r == r) {
        if(!on) return tr[u].cnt;
        else return tr[u].v;
    }
    push_down(u);
    int mid = (tr[u].l + tr[u].r) >> 1;
    if(r <= mid) return Query(u << 1,l,r,on);
    else if(l > mid) return Query(u << 1 | 1,l,r,on);
    else {
        int x = cmp(Query(u << 1,l,mid,on),Query(u << 1 | 1,mid + 1,r,on),on);
        if(on) {
            int pl = max(l,tr[u << 1].r - tr[u << 1].rl + 1),pr = min(r,tr[u << 1 | 1].l + tr[u << 1 | 1].ll - 1);
            x = max(x,pr - pl + 1);
        }
        return x;
    }
}
void Cover(int u,int l,int r,int v) {
    if(tr[u].l == l && tr[u].r == r) {cover(u,v);return;}
    push_down(u);
    int mid = (tr[u].l + tr[u].r) >> 1;
    if(r <= mid) Cover(u << 1,l,r,v);
    else if(l > mid) Cover(u << 1 | 1,l,r,v);
    else {Cover(u << 1,l,mid,v);Cover(u << 1 | 1,mid + 1,r,v);}
    update(u);
}
void repair(int u,int cnt) {
    if(!cnt) return;
    if(tr[u].l == tr[u].r) {cover(u,1);return;}
    push_down(u);
    if(tr[u << 1].r - tr[u << 1].l + 1 - tr[u << 1].cnt <= cnt) {
        cnt -= tr[u << 1].r - tr[u << 1].l + 1 - tr[u << 1].cnt;cover(u << 1,1);
        repair(u << 1 | 1,cnt);
    }
    else repair(u << 1,cnt);
    update(u);
}
int C;
void Repair(int u,int l,int r) {
    if(!C) return;
    if(tr[u].l == l && tr[u].r == r) {
        if(C >= r - l + 1 - tr[u].cnt) {
            C -= r - l + 1 - tr[u].cnt;
            cover(u,1);
        }
        else {repair(u,C);C = 0;}
        return;
    }
    int mid = (tr[u].l + tr[u].r) >> 1;
    push_down(u);
    if(r <= mid) Repair(u << 1,l,r);
    else if(l > mid) Repair(u << 1 | 1,l,r);
    else {Repair(u << 1,l,mid);Repair(u << 1 | 1,mid + 1,r);}
    update(u);
}
void Solve() {
    read(N);read(M);
    build(1,1,N);
    int op,l0,r0,l1,r1;
    for(int i = 1 ; i <= M ; ++i) {
        read(op);read(l0);read(r0);
        if(op == 1) {read(l1);read(r1);}
        if(op == 0) {
            Cover(1,l0,r0,0);
        }
        else if(op == 1) {
            C = Query(1,l0,r0,0);
            Cover(1,l0,r0,0);
            Repair(1,l1,r1);
        }
        else {
            out(Query(1,l0,r0,1));enter;
        }
    }
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

水题,但是我忘pushdown了,WA了一次,代码能力--

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/9489783.html