제출 #1348295

#제출 시각아이디문제언어결과실행 시간메모리
1348295avighnaMisspelling (JOI22_misspelling)C++20
60 / 100
4114 ms672464 KiB
#include <bits/stdc++.h>

using namespace std;

const int md = 1e9 + 7;

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);

  auto pow = [&](int64_t a, int b) {
    int64_t ans = 1, cur = a;
    while (b) {
      if (b & 1) {
        ans = (ans * cur) % md;
      }
      cur = (cur * cur) % md;
      b >>= 1;
    }
    return ans;
  };

  // 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));
  array<set<int>, 26> unowned, lt, gt, eq; // to maintain
  array<int64_t, 26> unowned_sum{}, lt_sum{}, gt_sum{};
  auto get_unowned = [&](int ch, int j) {
    int64_t ans = 0;
    for (int nch = 0; nch < 26; ++nch) {
      if (ch != nch) {
        ans = (ans + dp[j + 1][nch]) % md;
      }
    }
    return ans;
  };
  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;
    // travel to the next point where we have a constraint
    if (del == -1) {
      for (int nch = force_leq ? 0 : ch; nch <= (force_leq ? ch : 25); ++nch) {
        if (ch != nch) {
          ans = (ans + dp[constr][nch]) % md;
        }
      }
    } else {
      int mult = force_leq ? (ch * pow(26, del)) % md : ((25 - ch) * pow(26, del)) % md;
      if (constr == n) {
        ans = (ans + mult) % md;
      } else {
        for (int nch = 0; nch < 26; ++nch) {
          ans = (ans + (mult * dp[constr][nch]) % md) % 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].lower_bound(i); };
    for (auto it = next1(l); it != unowned[ch].end() && *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.lower_bound(i); };
    for (auto it = next2(l); it != st.end() && *it <= r; it = next2(l)) {
      eq[ch].insert(*it);
      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;
    }
  }

  int64_t ans = 0;
  for (int ch = 0; ch < 26; ++ch) {
    ans = (ans + dp[0][ch]) % md;
  }
  cout << ans << '\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...