BZOJ1858 [Scoi2010]序列操作(线段树)

题目链接 [Scoi2010]序列操作

考验代码能力的一道好题。

思想还是很简单的(直接上线段树),但是比较难写。

#include <bits/stdc++.h>

using namespace std;

#define REP(i,n)                for(int i(0); i <  (n); ++i)
#define rep(i,a,b)              for(int i(a); i <= (b); ++i)
#define dec(i,a,b)              for(int i(a); i >= (b); --i)
#define for_edge(i,x)           for(int i = H[x]; i; i = X[i])

#define LL      long long
#define ULL     unsigned long long
#define MP      make_pair
#define PB      push_back
#define FI      first
#define SE      second
#define INF     1 << 30

const int N     =    200000      +       10;
const int M     =    10000       +       10;
const int Q     =    1000        +       10;
const int A     =    30          +       1;

struct segTree{
    int len;
    int maxn[2], lmax[2], rmax[2], sum[2];
} segtree[N << 2];

int a[N], de_cover[N << 2], de_turn[N << 2];
int n, m, op, x, y;

segTree update(segTree x, segTree y){
    segTree ans;
    ans.len = x.len + y.len;
    rep(i, 0, 1){
        ans.sum[i] = x.sum[i] + y.sum[i];
        ans.lmax[i] = (x.lmax[i] == x.len ? x.len + y.lmax[i] : x.lmax[i]);
        ans.rmax[i] = (y.rmax[i] == y.len ? x.rmax[i] + y.len : y.rmax[i]);
        ans.maxn[i] = max(max(x.maxn[i], y.maxn[i]), max(ans.lmax[i], ans.rmax[i]));
        ans.maxn[i] = max(ans.maxn[i], x.rmax[i] + y.lmax[i]);
    }

    return ans;
}


void build(int i, int l, int r){
    if (l == r){
        int z = a[l];
        segtree[i].len = segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 1;
        segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0;
        de_cover[i] = -1, de_turn[i] = 0;
        return ;
    }

    int mid = (l + r) >> 1;
    build(i << 1, l, mid);
    build(i << 1 | 1, mid + 1, r);
    segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
    de_cover[i] = -1, de_turn[i] = 0;
}

void paint_cover(int i, int z){
    de_cover[i] = z;
    de_turn[i] = 0;
    segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = segtree[i].len;
    segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = 0;
}

void paint_turn(int i, int z){
    if (z != -1){
        de_cover[i] ^= 1;
        segtree[i].sum[z] = segtree[i].lmax[z] = segtree[i].rmax[z] = segtree[i].maxn[z] = 0;
        segtree[i].sum[z ^ 1] = segtree[i].lmax[z ^ 1] = segtree[i].rmax[z ^ 1] = segtree[i].maxn[z ^ 1] = segtree[i].len;
    }
    else{
        de_turn[i] ^= 1;
        swap(segtree[i].sum[0], segtree[i].sum[1]);
        swap(segtree[i].lmax[0], segtree[i].lmax[1]);
        swap(segtree[i].rmax[0], segtree[i].rmax[1]);
        swap(segtree[i].maxn[0], segtree[i].maxn[1]);
    }
}

void pushdown(int i){
    if (de_cover[i] != -1){
        paint_cover(i << 1, de_cover[i]);
        paint_cover(i << 1 | 1, de_cover[i]);
        de_cover[i] = -1;
    }
    if (de_turn[i]){
        paint_turn(i << 1, de_cover[i << 1]);
        paint_turn(i << 1 | 1, de_cover[i << 1 | 1]);
        de_turn[i] = 0;
    }
}

void insert_cover(int i, int l, int r, int x, int y, int z){
    if (x <= l && y >= r){
        paint_cover(i, z);
        return ;
    }

    pushdown(i);
    int mid = (l + r) >> 1;
    if (x <= mid) insert_cover(i << 1, l, mid, x, y, z);
    if (y > mid) insert_cover(i << 1 | 1, mid + 1, r, x, y, z);
    segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
}

void insert_turn(int i, int l, int r, int x, int y){
    if (x <= l && y >= r){
        paint_turn(i, de_cover[i]);
        return ;
    }

    pushdown(i);
    int mid = (l + r) >> 1;
    if (x <= mid) insert_turn(i << 1, l, mid, x, y);
    if (y > mid) insert_turn(i << 1 | 1, mid + 1, r, x, y);
    segtree[i] = update(segtree[i << 1], segtree[i << 1 | 1]);
}

int query_sum(int i, int l, int r, int x, int y){
    int sum = 0;
    if (x <= l && y >= r){ return segtree[i].sum[1];}
    int mid = (l + r) >> 1;
    pushdown(i);
    if (x <= mid) sum += query_sum(i << 1, l, mid, x, y);
    if (y > mid) sum += query_sum(i << 1 | 1, mid + 1, r, x, y);
    return sum;
}

segTree query_con(int i, int l ,int r, int x, int y){
    segTree ans1, ans2;
    bool f1 = false, f2 = false;
    if (x <= l && y >= r) return segtree[i];
    pushdown(i);

    int mid = (l + r) >> 1;
    if (x <= mid) ans1 = query_con(i << 1, l, mid, x, y), f1 = true;
    if (y > mid) ans2 = query_con(i << 1 | 1, mid + 1, r, x, y), f2 = true;
    if (f1 && f2) return update(ans1, ans2);
    else return f1 ? ans1 : ans2;
}



int main(){

    scanf("%d%d", &n, &m);
    rep(i, 1, n) scanf("%d", a + i);
    build(1, 1, n);
    while (m--){
        scanf("%d%d%d", &op, &x, &y);
        ++x, ++y;
        if (op == 0) insert_cover(1, 1, n, x, y, 0);
        if (op == 1) insert_cover(1, 1, n, x, y, 1);
        if (op == 2) insert_turn(1, 1, n, x, y);
        if (op == 3) printf("%d\n", query_sum(1, 1, n, x, y));
        if (op == 4) printf("%d\n", query_con(1, 1, n, x, y).maxn[1]);
    }

    return 0;

}

 

posted @ 2017-04-11 19:27  cxhscst2  阅读(144)  评论(0编辑  收藏  举报