不懂就问

P2572 [SCOI2010] 序列操作

chenwenmo @ 2024-07-15 20:15:46

为什么在push_down时要先赋值再取反


by light_searcher @ 2024-07-15 20:24:20

@chenwenmo 喜欢你的头像


by kinghku_dzk @ 2024-07-15 20:36:24

@chenwenmo (qiqi


by Jim_Franklin @ 2024-07-15 20:43:08

@light_searcher +1


by dist_22r @ 2024-07-15 21:50:49

不是要先取反再赋值吗?!


by chenwenmo @ 2024-07-16 08:44:09

@dist_22r 不知道呀 我看了第一篇题解 说先赋值再取反 我不懂才来问


by dist_22r @ 2024-07-16 09:40:40

@chenwenmo 粉兔写的感觉有点抽象,你可以看一下第二篇和第四篇题解


by dist_22r @ 2024-07-16 09:42:00

@chenwenmo 如果先赋值可能会导致取反标记直接清空,所以要先反转,同时也反转了赋值标记


by dist_22r @ 2024-07-16 09:44:00

@chenwenmo 我这样写的

void push_down(int u,int l,int r)
{
    int mid=(l+r)/2;
    if(lazyf[u])//先取反
    {
        t[ls]=mid-l+1-t[ls];
        swap(tl[ls][1],tl[ls][0]);
        swap(tr[ls][1],tr[ls][0]);
        swap(mt[ls][1],mt[ls][0]);
        if(lazy[ls]!=-1)
        {
            lazy[ls]^=1;
        }
        lazyf[ls]^=1;
        t[rs]=r-mid-t[rs];
        swap(tl[rs][1],tl[rs][0]);
        swap(tr[rs][1],tr[rs][0]);
        swap(mt[rs][1],mt[rs][0]);
        if(lazy[rs]!=-1)
        {
            lazy[rs]^=1;
        }
        lazyf[rs]^=1;
        lazyf[u]=0;
    }
    if(lazy[u]!=-1)//再考虑赋值
    {
        lazy[ls]=lazy[u];
        t[ls]=(mid-l+1)*lazy[u];
        tl[ls][lazy[u]]=mid-l+1;
        tr[ls][lazy[u]]=mid-l+1;
        mt[ls][lazy[u]]=mid-l+1;
        tl[ls][lazy[u]^1]=0;
        tr[ls][lazy[u]^1]=0;
        mt[ls][lazy[u]^1]=0;
        lazyf[ls]=0;
        lazy[rs]=lazy[u];
        t[rs]=(r-mid)*lazy[u];
        tl[rs][lazy[u]]=r-mid;
        tr[rs][lazy[u]]=r-mid;
        mt[rs][lazy[u]]=r-mid;
        tl[rs][lazy[u]^1]=0;
        tr[rs][lazy[u]^1]=0;
        mt[rs][lazy[u]^1]=0;
        lazyf[rs]=0;
        lazy[u]=-1;
    }
}

by chenwenmo @ 2024-07-16 10:02:23

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, m;
int a[N];

struct tree{
    int len;
    int l, r;
    int t1, t2;//t1修改, t2取反 
    int s0, s1;
    int m0, m1, l0, r0, l1, r1;
};
tree t[N * 4];

void push_up(int x){
    tree l = t[x * 2], r = t[x * 2 + 1];
    t[x].len = l.len + r.len;
    t[x].s0 = l.s0 + r.s0;
    t[x].s1 = l.s1 + r.s1;
    t[x].l1 = l.s0 ? l.l1 : (l.s1 + r.l1);
    t[x].r1 = r.s0 ? r.r1 : (r.s1 + l.r1);
    t[x].l0 = l.s1 ? l.l0 : (l.s0 + r.l0);
    t[x].r0 = r.s1 ? r.r0 : (r.s0 + l.r0);
    t[x].m1 = max(l.m1, max(l.r1 + r.l1, r.m1));
    t[x].m0 = max(l.m0, max(l.r0 + r.l0, r.m0));
}

void push_down(int x){
    int l = x * 2, r = x * 2 + 1;
    if(t[x].t1 == 0){
        t[l].t1 = t[r].t1 = 0;
        t[l].s1 = t[l].m1 = t[l].r1 = t[l].l1 = t[r].s1 = t[r].m1 = t[r].r1 = t[r].l1 = 0;
        t[l].s0 = t[l].m0 = t[l].l0 = t[l].r0 = t[l].len;
        t[r].s0 = t[r].m0 = t[r].l0 = t[r].r0 = t[r].len;
        t[l].t2 = t[r].t2 = 0;
    }
    if(t[x].t1 == 1){
        t[l].t1 = t[r].t1 = 1;
        t[l].s0 = t[l].m0 = t[l].r0 = t[l].l0 = t[r].s0 = t[r].m0 = t[r].r0 = t[r].l0 = 0;
        t[l].s1 = t[l].m1 = t[l].l1 = t[l].r1 = t[l].len;
        t[r].s1 = t[r].m1 = t[r].l1 = t[r].r1 = t[r].len;
        t[l].t2 = t[r].t2 = 0;
    }
    if(t[x].t2 == 1){
        t[l].t2 ^= 1;
        t[r].t2 ^= 1;
        swap(t[l].s1, t[l].s0);
        swap(t[l].m1, t[l].m0);
        swap(t[l].l1, t[l].l0);
        swap(t[l].r1, t[l].r0);
        swap(t[r].s1, t[r].s0);
        swap(t[r].m1, t[r].m0);
        swap(t[r].l1, t[r].l0);
        swap(t[r].r1, t[r].r0);
    }
    t[x].t1 = -1;
    t[x].t2 = 0;
}

void build(int x, int l, int r){
    t[x].l = l, t[x].r = r;
    t[x].t1 = -1;
    if(l == r){
        t[x].len = 1;
        t[x].m1 = t[x].s1 = t[x].l1 = t[x].r1 = a[l];
        t[x].m0 = t[x].s0 = t[x].l0 = t[x].r0 = !a[l];
        return;
    }
    int mid = l + r >> 1;
    build(x * 2, l, mid);
    build(x * 2 + 1, mid + 1, r);
    push_up(x);
}

void update(int x, int l, int r, int op){
    if(t[x].l >= l && t[x].r <= r){
        if(op == 0){
            t[x].t2 = 0;
            t[x].t1 = 0;
            t[x].s1 = t[x].m1 = t[x].r1 = t[x].l1 = 0;
            t[x].s0 = t[x].m0 = t[x].l0 = t[x].r0 = t[x].len;
        }else if(op == 1){
            t[x].t2 = 0;
            t[x].t1 = 1;
            t[x].s1 = t[x].m1 = t[x].r1 = t[x].l1 = t[x].len;
            t[x].s0 = t[x].m0 = t[x].l0 = t[x].r0 = 0;
        }else{
            t[x].t2 ^= 1;
            swap(t[x].s1, t[x].s0);
            swap(t[x].m1, t[x].m0);
            swap(t[x].l1, t[x].l0);
            swap(t[x].r1, t[x].r0);
        }
        return;
    }
    push_down(x);
    int mid = t[x].l + t[x].r >> 1;
    if(l <= mid) update(x * 2, l, r, op);
    if(r > mid) update(x * 2 + 1, l, r, op);
    push_up(x);
}

int query1(int x, int l, int r){
    if(t[x].l >= l && t[x].r <= r){
        return t[x].s1;
    }
    push_down(x);
    int mid = t[x].l + t[x].r >> 1, ans = 0;
    if(l <= mid) ans += query1(x * 2, l, r);
    if(r > mid) ans += query1(x * 2 + 1, l, r);
    return ans;
}

tree query2(int x, int l, int r){
    if(t[x].l >= l && t[x].r <= r){
        return t[x];
    }
    int mid = t[x].l + t[x].r >> 1;
    push_down(x); 
    if(r <= mid) return query2(x * 2, l, r);
    else if(l > mid) return query2(x * 2 + 1, l, r);
    else{
        tree ans, a = query2(x * 2, l, r), b = query2(x * 2 + 1, l, r);
        ans.s0 = a.s0 + b.s0;
        ans.s1 = a.s1 + b.s1;
        ans.l1 = a.s0 ? a.l1 : (a.s1 + b.l1);
        ans.r1 = b.s0 ? b.r1 : (b.s1 + a.r1);
        ans.l0 = a.s1 ? a.l0 : (a.s0 + b.l0);
        ans.r0 = b.s1 ? b.r0 : (b.s0 + a.r0);
        ans.m1 = max(a.m1, max(a.r1 + b.l1, b.m1));
        ans.m0 = max(a.m0, max(a.r0 + b.l0, b.m0));
        return ans;
    }
}

void check(int x, int l, int r){//调试用的 
    if(l == r){
        cout << t[x].s1 << ' ';
        return;
    }
    push_down(x);
    int mid = l + r >> 1;
    check(x * 2, l, mid);
    check(x * 2 + 1, mid + 1, r);
}

int main(){
    scanf("%d%d", &n, &m);
    for(int i = 0; i <= n - 1; i++){
        scanf("%d", &a[i]);
    }
    build(1, 0, n - 1);
    while(m--){
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if(op < 3){
            update(1, l, r, op);
        }else if(op == 3){
            int ans = query1(1, l, r);
            printf("%d\n", ans);
        }else{
            tree ans = query2(1, l, r);
            printf("%d\n", ans.m1);
        }
        //check(1, 0, n - 1);
        //cout << endl;
    }
    return 0;
}

by chenwenmo @ 2024-07-16 10:03:14

@dist_22r 改对了 这是ac代码 你看我push_down里面就是赋值再取反 换过来就错了 有点懵T_T


| 下一页