Submission #1348334

#TimeUsernameProblemLanguageResultExecution timeMemory
1348334avighnaMisspelling (JOI22_misspelling)C++20
100 / 100
1989 ms448604 KiB
#include <bits/stdc++.h>

using namespace std;

const int md = 1e9 + 7;

class fenw_set {
  int n;
  vector<int> bit;

public:
  fenw_set(int n) : n(n), bit(n + 1) {}

  void add(int i, int v) {
    for (++i; i <= n; i += i & -i) {
      bit[i] += v;
    }
  }

  int sum(int i) {
    int s = 0;
    for (++i; i > 0; i -= i & -i) {
      s += bit[i];
    }
    return s;
  }

  int size() { return sum(n - 1); }

  int kth(int k) {
    int pos = 0;
    for (int pw = bit_floor(unsigned(n)); pw; pw >>= 1) {
      if (pos + pw <= n && bit[pos + pw] < k) {
        k -= bit[pos + pw];
        pos += pw;
      }
    }
    return pos;
  }

  int next(int l) {
    int before = l == 0 ? 0 : sum(l - 1);
    int tot = size();
    if (before == tot) {
      return n;
    }
    return kth(before + 1);
  }

  void insert(int i) { add(i, 1); }
  void erase(int i) { add(i, -1); }
};

int main() {
  cin.tie(nullptr)->sync_with_stdio(false);

  int n, m;
  cin >> n >> m;
  vector<pair<int, int>> leqs, geqs;
  vector<vector<int>> lints(n), gints(n);
  for (int i = 0, a, b; i < m; ++i) {
    cin >> a >> b;
    --a, --b;
    if (a <= b) {
      leqs.push_back({a, b});
      lints[a].push_back(b - 1);
    } else {
      geqs.push_back({b, a});
      gints[b].push_back(a - 1);
    }
  }
  sort(leqs.begin(), leqs.end());
  sort(geqs.begin(), geqs.end());

  vector<int> firstl(n), firstg(n); // first interval such that l > i
  auto populate = [&](vector<int> &first, vector<pair<int, int>> ints) {
    for (int i = n - 1; i >= 0; --i) {
      while (!ints.empty() && ints.back().first > i) {
        ints.pop_back();
      }
      first[i] = ints.size();
    }
  };
  populate(firstl, leqs);
  populate(firstg, geqs);

  vector<int64_t> pows(n, 1);
  for (int i = 1; i < n; ++i) {
    pows[i] = (26 * pows[i - 1]) % md;
  }

  // dp[i][ch] = answer if we're at i, constraints behind i are all satisfied, and s[i] = ch
  vector dp(n, vector<int64_t>(26)), dpsum(n, vector<int64_t>(26));
  vector<fenw_set> unowned(26, fenw_set(n)), lt(26, fenw_set(n)), gt(26, fenw_set(n));
  array<int64_t, 26> unowned_sum{}, lt_sum{}, gt_sum{};
  auto get_unowned = [&](int ch, int j) {
    return ((dpsum[j + 1].back() - dp[j + 1][ch]) % md + md) % md;
  };
  auto insert_unowned = [&](int ch, int i) {
    unowned_sum[ch] += get_unowned(ch, i);
    unowned[ch].insert(i);
  };
  auto erase_unowned = [&](int ch, int i) {
    unowned_sum[ch] -= get_unowned(ch, i);
    unowned[ch].erase(i);
  };
  auto get_lt_gt = [&](int ch, int j, int force_leq) {
    int64_t ans = 0;
    int constrl = firstl[j] == leqs.size() ? n : leqs[firstl[j]].first;
    int constrg = firstg[j] == geqs.size() ? n : geqs[firstg[j]].first;
    int constr = min(constrl, constrg);
    int del = constr - j - 2;
    if (del == -1) {
      if (force_leq) {
        if (ch != 0) {
          ans = (ans + dpsum[constr][ch - 1]) % md;
        }
      } else {
        ans = (ans + (((dpsum[constr].back() - dpsum[constr][ch]) % md + md) % md)) % md;
      }
    } else {
      int mult = force_leq ? (ch * pows[del]) % md : ((25 - ch) * pows[del]) % md;
      if (constr == n) {
        ans = (ans + mult) % md;
      } else {
        ans = (ans + mult * dpsum[constr].back()) % md;
      }
    }
    return ans;
  };
  auto insert_lt = [&](int ch, int j) {
    lt_sum[ch] += get_lt_gt(ch, j, 1);
    lt[ch].insert(j);
  };
  auto erase_lt = [&](int ch, int j) {
    lt_sum[ch] -= get_lt_gt(ch, j, 1);
    lt[ch].erase(j);
  };
  auto insert_gt = [&](int ch, int j) {
    gt_sum[ch] += get_lt_gt(ch, j, 0);
    gt[ch].insert(j);
  };
  auto erase_gt = [&](int ch, int j) {
    gt_sum[ch] -= get_lt_gt(ch, j, 0);
    gt[ch].erase(j);
  };
  auto add_interval = [&](int ch, int l, int r, bool is_l) {
    auto next1 = [&](int i) { return unowned[ch].next(i); };
    for (auto it = next1(l); it <= r; it = next1(l)) {
      if (is_l) {
        insert_lt(ch, it);
      } else {
        insert_gt(ch, it);
      }
      erase_unowned(ch, it);
    }
    auto &st = (is_l ? gt : lt)[ch];
    auto next2 = [&](int i) { return st.next(i); };
    for (auto it = next2(l); it <= r; it = next2(l)) {
      if (is_l) {
        erase_gt(ch, it);
      } else {
        erase_lt(ch, it);
      }
    }
  };
  for (int i = n - 1; i >= 0; --i) {
    for (int ch = 0; ch < 26; ++ch) {
      dp[i][ch] = 1;
      if (i == n - 1) {
        continue;
      }
      insert_unowned(ch, i);
      for (auto &r : lints[i]) {
        add_interval(ch, i, r, 1);
      }
      for (auto &r : gints[i]) {
        add_interval(ch, i, r, 0);
      }
      dp[i][ch] = (dp[i][ch] + unowned_sum[ch]) % md;
      dp[i][ch] = (dp[i][ch] + lt_sum[ch]) % md;
      dp[i][ch] = (dp[i][ch] + gt_sum[ch]) % md;
    }
    dpsum[i][0] = dp[i][0];
    for (int ch = 1; ch < 26; ++ch) {
      dpsum[i][ch] = (dpsum[i][ch - 1] + dp[i][ch]) % md;
    }
  }

  cout << dpsum[0].back() << '\n';
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...