4号关注,线段树求助,内有极小的hack

P2572 [SCOI2010] 序列操作

Zelotz @ 2022-02-10 19:53:59

#include <bits/stdc++.h>
using namespace std;
#define srand srand(time(NULL))
#define random(x) rand() % (x)
#define il inline
#define ptc putchar
#define reg register
#define mp make_pair
typedef __int128 LL;
typedef long long ll;
typedef pair<int, int> PII;
namespace cyyh {
    template <typename T>
    il void read(T &x) {
        x = 0; T f = 1; char ch;
        while (!isdigit(ch = getchar())) f -= (ch == '-') << 1;
        while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch & 15), ch = getchar(); x *= f;
    }
    template <typename T>
    il void write(T x) {
        if (x < 0) ptc('-'), x = -x;
        if (x > 9) write(x / 10);
        ptc(x % 10 + '0');
    }
    template <typename T>
    il T lowbit(const T &x) {
        return x & -x;
    }
}
using namespace cyyh; 
const int N = 4e5 + 5;
int n, m, a[N];
struct node {
    int sum0, sum1, mx0, mx1, zq0, zq1, yq0, yq1, tag;
    // tag1表示区间更改的数,初始值为-1
    // tag2表示区间是否取反
    // sum表示区间内该数字的个数
    // mx表示区间内该数字的最大的连续一段
    // zq表示区间左端点开始该数最长的连续个数
    // yq表示区间右端点开始该数最长的连续个数
} tr[N];
void pushup(int id, int l, int r) {
    int ls = id << 1, rs = id << 1 | 1;
    tr[id].sum0 = tr[ls].sum0 + tr[rs].sum0;
    tr[id].sum1 = tr[ls].sum1 + tr[rs].sum1;
    tr[id].mx0 = max(tr[ls].yq0 + tr[rs].zq0, max(tr[ls].mx0, tr[rs].mx0));
    tr[id].mx1 = max(tr[ls].yq1 + tr[rs].zq1, max(tr[ls].mx1, tr[rs].mx1));
    tr[id].zq0 = tr[ls].zq0, tr[id].yq0 = tr[rs].yq0;
    tr[id].zq1 = tr[ls].zq1, tr[id].yq1 = tr[rs].yq1;
    int mid = l + r >> 1;
    if (tr[ls].zq0 == mid - l + 1) tr[id].zq0 += tr[rs].zq0;
    if (tr[ls].zq1 == mid - l + 1) tr[id].zq1 += tr[rs].zq1;
    if (tr[ls].yq0 == r - mid) tr[id].yq0 += tr[rs].yq0;
    if (tr[ls].yq1 == r - mid) tr[id].yq1 += tr[rs].yq1;
}
void pushdown(int id, int l, int r) {
    int mid = l + r >> 1, ls = id << 1, rs = id << 1 | 1;
    if (tr[id].tag == -1) return ;
    if (!tr[id].tag) {
        tr[ls].tag = tr[ls].mx1 = tr[ls].sum1 = tr[ls].yq1 = tr[ls].zq1 = 0;
        tr[ls].mx0 = tr[ls].sum0 = tr[ls].yq0 = tr[ls].zq0 = mid - l + 1;
        tr[rs].tag = tr[rs].mx1 = tr[rs].sum1 = tr[rs].yq1 = tr[rs].zq1 = 0;
        tr[rs].mx0 = tr[rs].sum0 = tr[rs].yq0 = tr[rs].zq0 = r - mid;
    } else if (tr[id].tag == 1) {
        tr[ls].tag = 1;
        tr[ls].mx0 = tr[ls].sum0 = tr[ls].yq0 = tr[ls].zq0 = 0;
        tr[ls].mx1 = tr[ls].sum1 = tr[ls].yq1 = tr[ls].zq1 = mid - l + 1;
        tr[rs].tag = 1;
        tr[rs].mx0 = tr[rs].sum0 = tr[rs].yq0 = tr[rs].zq0 = 0;
        tr[rs].mx1 = tr[rs].sum1 = tr[rs].yq1 = tr[rs].zq1 = r - mid;
    } else {
        swap(tr[ls].mx0, tr[ls].mx1);
        swap(tr[ls].sum0, tr[ls].sum1);
        swap(tr[ls].yq0, tr[ls].yq1);
        swap(tr[ls].zq0, tr[ls].zq1);
        if (tr[ls].tag == 1 || tr[ls].tag == 0) tr[ls].tag = !tr[ls].tag;
        else if (tr[ls].tag == -1) tr[ls].tag = 2;
        else tr[ls].tag = -1;
        swap(tr[rs].mx0, tr[rs].mx1);
        swap(tr[rs].sum0, tr[rs].sum1);
        swap(tr[rs].yq0, tr[rs].yq1);
        swap(tr[rs].zq0, tr[rs].zq1);
        if (tr[rs].tag == 1 || tr[rs].tag == 0) tr[rs].tag = !tr[rs].tag;
        else if (tr[rs].tag == -1) tr[rs].tag = 2;
        else tr[rs].tag = -1;
    }
    tr[id].tag = -1;
}
void modify(int l, int r, int x, int y, int id, int op) {
    // op为指定操作 
    if (l > y || r < x) return ;
    if (l >= x && r <= y) {
        if (!op) {
            tr[id].mx1 = tr[id].sum1 = tr[id].tag = tr[id].yq1 = tr[id].zq1 = 0;
            tr[id].sum0 = tr[id].mx0 = tr[id].yq0 = tr[id].zq0 = r - l + 1;
        } else if (op == 1) {
            tr[id].tag = 1;
            tr[id].mx1 = tr[id].sum1 = tr[id].tag = tr[id].yq1 = r - l + 1;
            tr[id].sum0 = tr[id].mx0 = tr[id].yq0 = tr[id].zq0 = 0;
        } else {
            swap(tr[id].mx0, tr[id].mx1);
            swap(tr[id].sum0, tr[id].sum1);
            swap(tr[id].yq0, tr[id].yq1);
            swap(tr[id].zq0, tr[id].yq1);
//          if(~tr[id].tag && tr[id].tag != 2) tr[id].tag ^= 1;
//          else tr[id].tag = (tr[id].tag == 2 ? -1 : 2);
            if (tr[id].tag == 1 || tr[id].tag == 0) tr[id].tag = !tr[id].tag;
            else if (tr[id].tag == -1) tr[id].tag = 2;
            else tr[id].tag = -1;
        } 
        return ;
    }
    pushdown(id, l, r);
    int mid = l + r >> 1;
    modify(l, mid, x, y, id << 1, op), modify(mid + 1, r, x, y, id << 1 | 1, op);
    pushup(id, l, r);
}
int query(int l, int r, int x, int y, int id) {
    if (l > y || r < x) return 0;
    if (l >= x && r <= y) return tr[id].sum1;
    int mid = l + r >> 1;
    pushdown(id << 1, l, r);
    return query(l, mid, x, y, id << 1) + query(mid + 1, r, x, y, id << 1 | 1);
}
node query2(int l, int r, int x, int y, int id) {
    if (l >= x && r <= y) return tr[id];
    int mid = l + r >> 1, ls = id << 1, rs = id << 1 | 1;
    pushdown(id, l, r);
    if (y <= mid) return query2(l, mid, x, y, ls);
    else if (x > mid) return query2(mid + 1, r, x, y, rs);
    node a = query2(l, mid, x, y, ls), b = query2(mid + 1, r, x, y, rs), res;
    // pushup
    res.mx1 = max(a.yq1 + b.zq1, max(a.mx1, b.mx1));
    res.zq1 = a.zq1, res.yq1 = b.yq1;
    if (a.zq1 == mid - l + 1) res.zq1 += b.zq1;
    if (b.yq1 == r - mid) res.yq1 += a.yq1;
    return res;
}
void build(int l, int r, int id) {
    tr[id].tag = -1;
    if (l == r) {
        tr[id].mx0 = tr[id].sum0 = tr[id].yq0 = tr[id].zq0 = !a[l];
        tr[id].mx1 = tr[id].sum1 = tr[id].yq1 = tr[id].zq1 = a[l];
        return ;
    }
    int mid = l + r >> 1;
    build(l, mid, id << 1), build(mid + 1, r, id << 1 | 1);
    pushup(id, l, r);
}
int main() {
    read(n), read(m);
    for (int i = 1; i <= n; ++i) read(a[i]);
    build(1, n, 1);
    //modify(1, n, 2, 3, 1, 2);
//  for (int i = 1; i <= n; ++i) {
//      for (int j = i; j <= n; ++j) {
//          cout << i << ' ' << j << ' ' << query(1, n, i, j, 1) << ' ' << endl;
//      }
//  }
    //write(query(1, n, 1, 3, 1)), ptc('\n');
//  return 0;
    while (m--) {
        int op, l, r;
        read(op), read(l), read(r);
        ++l, ++r;
        if (op == 0) modify(l, r, 1, n, 1, 0);
        else if (op == 1) modify(1, n, l, r, 1, 1);
        else if (op == 2) modify(1, n, l, r, 1, 2);
        else if (op == 3) write(query(1, n, l, r, 1)), ptc('\n');
        else if (op == 4) write(query2(1, n, l, r, 1).mx1), ptc('\n');
    }
    return 0;
}

萌新第4次写线段树,hack如下:

3 2
1 0 0
2 1 2
4 0 2

答案显然是3,而modify确实修改成功了的,查询的时候却总是出错,但是查询我死活看不出来问题在哪


by lrc_wbb @ 2022-02-10 19:57:11

舅舅那个孩子吧~


by cinnamon_husky @ 2022-02-10 20:12:43

@lrc_wbb 你怎么拿小号水帖了


by rp_INF @ 2022-02-10 20:42:13

@Frightened 为什么要用线段树呢/kk


by Zelotz @ 2022-02-10 20:48:02

@rp_INF 我们上课布置的题,其实我也畏惧线段树...


by Zelotz @ 2022-02-10 20:49:20

上面的代码已经调出来一些小错误了...

感觉还有很多...


by Zelotz @ 2022-02-10 21:01:08

傻了,线段树传参写反了

焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯焯


|