蒟蒻求正解 :)P2572 [SCOI2010] 序列操作

题面
事情是这样的,看到标签是线段树,就果断手搓了一个线段树。
可我学艺不精,那个代码只过了 Subtask #1 ,WA0代码如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn = 1e5 + 10;
struct SegmentTree {
    int l, r;
    int sum;
    int lmax, rmax, mmax;
    int lazy;
} tree[maxn << 2];
int a[maxn];

void push_up(int rt) {
    tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
    tree[rt].lmax = max(tree[rt << 1].lmax, tree[rt << 1].sum + tree[rt << 1 | 1].lmax);
    tree[rt].rmax = max(tree[rt << 1 | 1].rmax, tree[rt << 1 | 1].sum + tree[rt << 1].rmax);
    tree[rt].mmax = max(tree[rt << 1].rmax + tree[rt << 1 | 1].lmax, max(tree[rt << 1].mmax, tree[rt << 1 | 1].mmax));
}

void build(int rt, int l, int r) {
    tree[rt].l = l;
    tree[rt].r = r;
    tree[rt].lazy = -1;
    if (l == r) {
        tree[rt].sum = a[l];
        tree[rt].lmax = a[l];
        tree[rt].rmax = a[l];
        tree[rt].mmax = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(rt << 1, l, mid);
    build(rt << 1 | 1, mid + 1, r);
    push_up(rt);
}

void push_down(int rt) {
    if (tree[rt].lazy!= -1) {
        int lazy = tree[rt].lazy;
        tree[rt << 1].lazy = lazy;
        tree[rt << 1 | 1].lazy = lazy;
        if (lazy == 0) {
            tree[rt << 1].sum = 0;
            tree[rt << 1].lmax = 0;
            tree[rt << 1].rmax = 0;
            tree[rt << 1].mmax = 0;
            tree[rt << 1 | 1].sum = 0;
            tree[rt << 1 | 1].lmax = 0;
            tree[rt << 1 | 1].rmax = 0;
            tree[rt << 1 | 1].mmax = 0;
        } else if (lazy == 1) {
            tree[rt << 1].sum = tree[rt << 1].r - tree[rt << 1].l + 1;
            tree[rt << 1].lmax = tree[rt << 1].r - tree[rt << 1].l + 1;
            tree[rt << 1].rmax = tree[rt << 1].r - tree[rt << 1].l + 1;
            tree[rt << 1].mmax = tree[rt << 1].r - tree[rt << 1].l + 1;
            tree[rt << 1 | 1].sum = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1;
            tree[rt << 1 | 1].lmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1;
            tree[rt << 1 | 1].rmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1;
            tree[rt << 1 | 1].mmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1;
        } else {
            tree[rt << 1].sum = tree[rt << 1].r - tree[rt << 1].l + 1 - tree[rt << 1].sum;
            swap(tree[rt << 1].lmax, tree[rt << 1].rmax);
            tree[rt << 1].lmax = tree[rt << 1].r - tree[rt << 1].l + 1 - tree[rt << 1].lmax;
            tree[rt << 1].rmax = tree[rt << 1].r - tree[rt << 1].l + 1 - tree[rt << 1].rmax;
            tree[rt << 1].mmax = tree[rt << 1].r - tree[rt << 1].l + 1 - tree[rt << 1].mmax;
            tree[rt << 1 | 1].sum = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1 - tree[rt << 1 | 1].sum;
            swap(tree[rt << 1 | 1].lmax, tree[rt << 1 | 1].rmax);
            tree[rt << 1 | 1].lmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1 - tree[rt << 1 | 1].lmax;
            tree[rt << 1 | 1].rmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1 - tree[rt << 1 | 1].rmax;
            tree[rt << 1 | 1].mmax = tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1 - tree[rt << 1 | 1].mmax;
        }
        tree[rt].lazy = -1;
    }
}

void update(int rt, int l, int r, int val) {
    if (l <= tree[rt].l && tree[rt].r <= r) {
        if (val == 0) {
            tree[rt].sum = 0;
            tree[rt].lmax = 0;
            tree[rt].rmax = 0;
            tree[rt].mmax = 0;
            tree[rt].lazy = 0;
        } else if (val == 1) {
            tree[rt].sum = tree[rt].r - tree[rt].l + 1;
            tree[rt].lmax = tree[rt].r - tree[rt].l + 1;
            tree[rt].rmax = tree[rt].r - tree[rt].l + 1;
            tree[rt].mmax = tree[rt].r - tree[rt].l + 1;
            tree[rt].lazy = 1;
        } else {
            tree[rt].sum = tree[rt].r - tree[rt].l + 1 - tree[rt].sum;
            swap(tree[rt].lmax, tree[rt].rmax);
            tree[rt].lmax = tree[rt].r - tree[rt].l + 1 - tree[rt].lmax;
            tree[rt].rmax = tree[rt].r - tree[rt].l + 1 - tree[rt].rmax;
            tree[rt].mmax = tree[rt].r - tree[rt].l + 1 - tree[rt].mmax;
            tree[rt].lazy = 2;
        }
        return;
    }
    push_down(rt);
    int mid = (tree[rt].l + tree[rt].r) >> 1;
    if (l <= mid) update(rt << 1, l, r, val);
    if (r > mid) update(rt << 1 | 1, l, r, val);
    push_up(rt);
}

int query_sum(int rt, int l, int r) {
    if (l <= tree[rt].l && tree[rt].r <= r) {
        return tree[rt].sum;
    }
    push_down(rt);
    int mid = (tree[rt].l + tree[rt].r) >> 1;
    int ans = 0;
    if (l <= mid) ans += query_sum(rt << 1, l, r);
    if (r > mid) ans += query_sum(rt << 1 | 1, l, r);
    return ans;
}

int query_max(int rt, int l, int r) {
    if (l <= tree[rt].l && tree[rt].r <= r) {
        return tree[rt].mmax;
    }
    push_down(rt);
    int mid = (tree[rt].l + tree[rt].r) >> 1;
    if (r <= mid) return query_max(rt << 1, l, r);
    else if (l > mid) return query_max(rt << 1 | 1, l, r);
    else {
        int leftmax = query_max(rt << 1, l, mid);
        int rightmax = query_max(rt << 1 | 1, mid + 1, r);
        int crossmax = min(mid - l + 1, tree[rt << 1].rmax) + min(r - mid, tree[rt << 1 | 1].lmax);
        return max(crossmax, max(leftmax, rightmax));
    }
}

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    build(1, 0, n - 1);
    for (int i = 0; i < m; i++) {
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if (op == 0) {
            update(1, l, r, 0);
        } else if (op == 1) {
            update(1, l, r, 1);
        } else if (op == 2) {
            update(1, l, r, 2);
        } else if (op == 3) {
            printf("%d\n", query_sum(1, l, r));
        } else if (op == 4) {
            printf("%d\n", query_max(1, l, r));
        }
    }
    return 0;
}

我意识到应该是 query_max 写错了,但是蒟蒻不会改。。。暴力了一下,《WA100》:

#include <bits/stdc++.h>

using namespace std;

int main(void)
{
	int n, m;
	cin >> n >> m;
	
	vector<int> a(n);
	
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	
	while (m--) {
		int ch, l, r;
		cin >> ch >> l >> r;
		
		if (ch == 0) {
			for (int i = l; i <= r; i++) {
				a[i] = 0;
			}
		} else if (ch == 1) {
			for (int i = l; i <= r; i++) {
				a[i] = 1;
			}
		} else if (ch == 2) {
			for (int i = l; i <= r; i++) {
				a[i] ^= 1;
			}
		} else if (ch == 3) {
			int cnt = 0;
			for (int i = l; i <= r; i++) {
				if (a[i] == 1) {
					cnt++;
				}
			}
			cout << cnt << '\n';
		} else if (ch == 4) {
			int ans = 0;
			int cnt = 0;
			for (int i = l; i <= r; i++) {
				if (a[i] == 1) {
					cnt++;
				} else {
					cnt = 0;
				}
				ans = max(ans, cnt);
			}
			cout << ans << '\n';
		}
	}
	
	return 0;
}

数据过水。我除了 Subtask #1 其他都过了,于是开始尝试两个代码融合,在我的骗分大法的加持下,我过了?。太水了吧。。。

求dalao告诉我正解,或者帮我改一下第一个代码

不会操作4

emm……