E. Lucky Queries

Description:

Petya loves lucky numbers very much. Everybody knows that lucky numbers are positive integers whose decimal record contains only the lucky digits 4 and 7. For example, numbers 47, 744, 4 are lucky and 5, 17, 467 are not.
Petya brought home string s with the length of n. The string only consists of lucky digits. The digits are numbered from the left to the right starting with 1. Now Petya should execute m queries of the following form:

  • switch l r — “switch” digits (i.e. replace them with their opposites) at all positions with indexes from l to r, inclusive: each digit 4 is replaced with 7 and each digit 7 is replaced with 4 (1 ≤ l ≤ r ≤ n);
  • count — find and print on the screen the length of the longest non-decreasing subsequence of string s.

Subsequence of a string s is a string that can be obtained from s by removing zero or more of its elements. A string is called non-decreasing if each successive digit is not less than the previous one.
Help Petya process the requests.

Input:

The first line contains two integers n and m (1 ≤ n ≤ 106, 1 ≤ m ≤ 3·105) — the length of the string s and the number of queries correspondingly. The second line contains n lucky digits without spaces — Petya’s initial string. Next m lines contain queries in the form described in the statement.

Output

For each query count print an answer on a single line.

Sample Input:

2 3
47
count
switch 1 2
count

Sample Output:

2
1

Sample Input:

3 5
747
count
switch 1 1
count
switch 1 3
count

Sample Output:

2
3
2

题目链接

有一串只有 4 4 4 7 7 7 的数列,需要支持两种操作

  1. switch l r 将区间 [ l , r ] [l,r] [l,r] 内的 4 4 4 变为 7 7 7 7 7 7 变为 4 4 4
  2. count 求整个数列的最长不下降子序列长度

看题目范围很容易想到线段树做法,其中对线段树每个节点四个属性:覆盖区间内 4 4 4 的数量、 7 7 7 的数量、最长不下降子序列长度、最长不上升子序列长度

其中进行区间更新时把 4 7 4、7 47 的数量互换,把最长不下降子序列长度、最长不上升子序列长度互换

而进行更新上传时时计算最长不下降子序列有三种情况

  1. 左子树最长不下降子序列长度+右子树 7 7 7 的数量
  2. 左子树 4 4 4 的数量+右子树最长不下降子序列长度
  3. 左子树 4 4 4 的数量+右子树 7 7 7 的数量

其中对三种情况取最大值即可,计算最长不上升子序列同理

AC代码:

#include <bits/stdc++.h>
using namespace std;

class seg_tree {
public:
  typedef int type_t;
  struct node {
    type_t cnt4, cnt7, rise, fall, lazy;
    node(type_t _cnt4 = 0, type_t _cnt7 = 0,
         type_t _rise = 1, type_t _fall = 1,
         type_t _lazy = 0): cnt4(_cnt4), cnt7(_cnt7), 
                            rise(_rise), fall(_fall),
                            lazy(_lazy) {}
  };

  int n;
  vector<node> tree;

  node Unite(const node &k1, const node &k2) {
    node ans;
    ans.cnt4 = k1.cnt4 + k2.cnt4;
    ans.cnt7 = k1.cnt7 + k2.cnt7;
    ans.rise = max(k1.rise + k2.cnt7, max(k1.cnt4 + k2.cnt7, k1.cnt4 + k2.rise));
    ans.fall = max(k1.fall + k2.cnt4, max(k1.cnt7 + k2.cnt4, k1.cnt7 + k2.fall));
    return ans;
  }

  void Pull(int o) {
    tree[o] = Unite(tree[o << 1], tree[o << 1 | 1]);
  }

  void Push(int o, int l, int r) {
    if (tree[o].lazy != 0) {
      swap(tree[o << 1].cnt4, tree[o << 1].cnt7);
      swap(tree[o << 1].rise, tree[o << 1].fall);
      swap(tree[o << 1 | 1].cnt4, tree[o << 1 | 1].cnt7);
      swap(tree[o << 1 | 1].rise, tree[o << 1 | 1].fall);
      tree[o << 1].lazy = !tree[o << 1].lazy;
      tree[o << 1 | 1].lazy = !tree[o << 1 | 1].lazy;
      tree[o].lazy = 0;
    }
  }

  void Build(int o, int l, int r, const vector<type_t> &v) {
    if (l == r) {
      tree[o].cnt4 = (v[l - 1] == 4);
      tree[o].cnt7 = (v[l - 1] == 7);
      return;
    }
    int m = (l + r) >> 1;
    Build(o << 1, l, m, v);
    Build(o << 1 | 1, m + 1, r, v);
    Pull(o);
  }

  seg_tree(const vector<type_t> &v) {
    n = v.size();
    tree.resize(n << 2);
    Build(1, 1, n, v);
  }

  void Modify(int o, int l, int r, int ll, int rr) {
    if (ll <= l && rr >= r) {
      swap(tree[o].cnt4, tree[o].cnt7);
      swap(tree[o].rise, tree[o].fall);
      tree[o].lazy = !tree[o].lazy;
      return;
    }
    Push(o, l, r);
    int m = (l + r) >> 1;
    if (ll <= m) Modify(o << 1, l, m, ll, rr);
    if (rr > m) Modify(o << 1 | 1, m + 1, r, ll, rr);
    Pull(o);
  }
  void Modify(int ll, int rr) {
    Modify(1, 1, n, ll, rr);
  }
};

int main() {
  ios::sync_with_stdio(false); cin.tie(0);
  int n, m; cin >> n >> m;
  vector<int> arr(n);
  for (int i = 0; i < n; ++i) {
    char x; cin >> x;
    arr[i] = x - '0';
  }
  seg_tree sgt(arr);
  for (int i = 0, l, r; i < m; ++i) {
    string s; cin >> s;
    if (s == "count") cout << sgt.tree[1].rise << endl;
    else {
      cin >> l >> r;
      sgt.Modify(l, r);
    }
  }
  return 0;
}