zoukankan      html  css  js  c++  java
  • 洛谷 P2572 [SCOI2010]序列操作

    瞎扯

    好久没写线段树了,找了一道线段树题
    然后……

    写了半个上午,调了半个上午+下午的半个小时……
    没 谁 了

    思路

    这道题难就难在标记的下放,如果标记下放正确了,A这道题就不是问题了。(然而我不想讲下放= =)

    如果没有 (4) 操作和 (2) 操作,需要维护的东西就很少了,只需要维护区间内 (1) 的个数。但是因为有 (4) 操作和 (2) 操作,所以我们还要记录几个信息:左端最长的 (0)、左端最长的 (1)、右端最长的 (0)、右端最长的 (1)、区间最长的连续的 (0)、区间最长的连续的 (1)(这里说的哪个端是从区间端点开始的),这样才能实现 (2) 操作和 (4) 操作。

    下面看一下两区间合并时,信息如何合并:

    1. 左端最长连续的 (0) = 左区间左端最长连续的 (0) + {右区间左端最长连续的 (0)(如果左区间最长连续的 (0) 的个数等于左区间长度)}
    2. 左端最长连续的 (1) = 左区间左端最长连续的 (1) + {右区间左端最长连续的 (1)(如果左区间最长连续的 (1) 的个数等于左区间长度)}
    3. 右端最长连续的 (0) = 右区间右端最长连续的 (0) + {左区间右端最长连续的 (0)(如果右区间最长连续的 (0) 的个数等于右区间长度)}
    4. 右端最长连续的 (1) = 右区间右端最长连续的 (1) + {左区间右端最长连续的 (1)(如果右区间最长连续的 (1) 的个数等于右区间长度)}
    5. 区间内 (1) 的个数 = 左区间内 (1) 的个数 + 右区间内 (1) 的个数
    6. 区间最长连续的 (1) = (max()左区间最长连续 (1),右区间最长连续 (1), 左区间右端最长连续 (1) + 右区间左端最长连续 (1) ())
    7. 区间最长连续的 (0) = (max()左区间最长连续 (0),右区间最长连续 (0), 左区间右端最长连续 (0) + 右区间左端最长连续 (0) ())

    然后要注意的就是标记的下传了,这里我们采用两个标记,一个赋值标记,一个取反标记,显然赋值标记的优先级是大于取反标记的(其实我不知道为啥,就凭感觉觉得这样是对的,评论区大佬可否解答?),所以我们先处理赋值标记,在处理赋值标记后,注意取反标记的贡献应该取消,在处理取反标记时,赋值标记也要取反……详细的实现可以看代码了……

    代码

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson rt << 1
    #define rson rt << 1 | 1
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
      char c = getchar(); int x = 0, f = 1;
      for ( ; !isdigit(c); c = getchar()) if (c == '-') f = -1;
      for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
      return x * f;
    }
    
    int n, m, a[A];
    struct node {
      int sum1, l1, r1, max1;
      void clear() { sum1 = 0, l1 = 0, r1 = 0, max1 = 0; }
    };
    struct tree { 
      int l, r, sum0, sum1, l0, l1, r0, r1, max1, max0, lazy1, lazy2; 
    } t[A << 2];
    
    inline void pushup(int rt) {
      t[rt].sum0 = t[lson].sum0 + t[rson].sum0;
      t[rt].sum1 = t[lson].sum1 + t[rson].sum1;
      t[rt].max0 = max(max(t[lson].max0, t[rson].max0), t[lson].r0 + t[rson].l0);  
      t[rt].max1 = max(max(t[lson].max1, t[rson].max1), t[lson].r1 + t[rson].l1);
      t[rt].l0 = t[lson].l0 + t[rson].l0 * (t[lson].l0 == (t[lson].r - t[lson].l + 1));
      t[rt].l1 = t[lson].l1 + t[rson].l1 * (t[lson].l1 == (t[lson].r - t[lson].l + 1));
      t[rt].r0 = t[rson].r0 + t[lson].r0 * (t[rson].r0 == (t[rson].r - t[rson].l + 1));
      t[rt].r1 = t[rson].r1 + t[lson].r1 * (t[rson].r1 == (t[rson].r - t[rson].l + 1));
      return;
    }
    
    inline void tag(int rt) {
      swap(t[rt].max0, t[rt].max1);
      swap(t[rt].sum0, t[rt].sum1);
      swap(t[rt].r0, t[rt].r1);
      swap(t[rt].l0, t[rt].l1);
      t[rt].lazy2 ^= 1, t[rt].lazy1 ^= 1;
      return;
    }
    
    inline void change1(int rt) {
      int len = t[rt].r - t[rt].l + 1;
      t[rt].sum0 = 0, t[rt].max0 = 0, t[rt].l0 = 0, t[rt].r0 = 0;
      t[rt].sum1 = len, t[rt].max1 = len, t[rt].l1 = len, t[rt].r1 = len;
      t[rt].lazy1 = 1, t[rt].lazy2 = 0;
      return;
    }
    
    inline void change0(int rt) {
      int len = t[rt].r - t[rt].l + 1;
      t[rt].sum1 = 0, t[rt].max1 = 0, t[rt].l1 = 0, t[rt].r1 = 0;
      t[rt].sum0 = len, t[rt].max0 = len, t[rt].l0 = len, t[rt].r0 = len;
      t[rt].lazy1 = 0, t[rt].lazy2 = 0;
      return;
    }
    
    inline void pushdown(int rt) {
      if (t[rt].lazy1 == 1) {
        change1(lson), change1(rson);
        t[rt].lazy1 = -1, t[rt].lazy2 = 0;
      }
      else if (t[rt].lazy1 == 0) {
        change0(lson), change0(rson);
        t[rt].lazy1 = -1, t[rt].lazy2 = 0;
      }
      if (t[rt].lazy2 == 1) {
        tag(lson), tag(rson);
        t[rt].lazy2 = 0, t[rt].lazy1 = -1;
      } 
    }
    
    void build(int rt, int l, int r) {
      t[rt].l = l, t[rt].r = r, t[rt].lazy1 = -1;
      if (l == r) {
        int now = a[l];
        if (now == 1) {
          t[rt].l1 = 1, t[rt].r1 = 1;
          t[rt].sum1 = 1, t[rt].max1 = 1;
        }
        else {
          t[rt].l0 = 1, t[rt].r0 = 1;
          t[rt].sum0 = 1, t[rt].max0 = 1;
        }
        return;
      }
      int mid = (l + r) >> 1;
      build(lson, l, mid), build(rson, mid + 1, r);
      pushup(rt);
    }
    
    void update(int rt, int l, int r, int who) {
      if (l <= t[rt].l && t[rt].r <= r) {
        pushdown(rt);
        if (who) {
          change1(rt);
        } else {
          change0(rt);
        }
        return;
      }
      pushdown(rt);
      int mid = (t[rt].l + t[rt].r) >> 1;
      if (l <= mid) {
        update(lson, l, r, who);
      }
      if (r > mid) {
        update(rson, l, r, who);
      }
      pushup(rt); 
    }
    
    void Negate(int rt, int l, int r) {
      if (l <= t[rt].l && t[rt].r <= r) {
        pushdown(rt);
        tag(rt);
        return;
      }
      pushdown(rt);
      int mid = (t[rt].l + t[rt].r) >> 1;
      if (l <= mid) Negate(lson, l, r);
      if (r > mid) Negate(rson, l, r);
      pushup(rt); 
    }
    
    node conseq(int rt, int l, int r) {
      node now, ls, rs;
      now.clear(), ls.clear(), rs.clear();
      if (l <= t[rt].l && t[rt].r <= r) {
        now.l1 = t[rt].l1, now.max1 = t[rt].max1, now.r1 = t[rt].r1, now.sum1 = t[rt].sum1; 
        return now;
      }
      pushdown(rt);
      int mid = (t[rt].l + t[rt].r) >> 1;
      if (l <= mid) ls = conseq(lson, l, r);
      if (r > mid) rs = conseq(rson, l, r);
      now.sum1 = ls.sum1 + rs.sum1;
      now.max1 = max(max(ls.max1, rs.max1), ls.r1 + rs.l1);
      now.l1 = ls.l1 + rs.l1 * (ls.l1 == (t[lson].r - t[lson].l + 1));
      now.r1 = rs.r1 + ls.r1 * (rs.r1 == (t[rson].r - t[rson].l + 1));
      return now;
    }
    
    int main() {
      n = read(), m = read();
      for (int i = 1; i <= n; i++) a[i] = read();
      build(1, 1, n);
      while (m--) {
        int opt = read(), x = read() + 1, y = read() + 1;
        if (opt == 1 || opt == 0) update(1, x, y, opt);
        else if (opt == 2) Negate(1, x, y);
        else if (opt == 3) cout << conseq(1, x, y).sum1 << '
    ';
        else if (opt == 4) cout << conseq(1, x, y).max1 << '
    ';
      }
      return 0;
    }
    
  • 相关阅读:
    第二次冲刺周期站立会议(3)
    第二次冲刺周期站立会议(2)
    第二次冲刺周期站立会议(1)
    测试计划
    对各组第一次冲刺周期的评价
    团队绩效评估计划
    学校网站UI设计分析
    站立会议(10)
    Bower和Gulp集成前端资源
    Laravel的学习网站推荐
  • 原文地址:https://www.cnblogs.com/loceaner/p/13705613.html
Copyright © 2011-2022 走看看