2025--煉石計劃-- 11 月 23 日 --NOIP 模擬賽 #23

ccxswl發表於2024-11-24

2025--煉石計劃-- 11 月 23 日 --NOIP 模擬賽 #23

現在習慣 Ctrl+z 儲存了,用 vscode 的時候老是撤銷怎麼辦(

T1 沒營養,T3 對於 noip 沒營養。

T2 明天寫。


T4 莫隊

非常可惜,賽時想到了維護 \(lst_i\)\(g_i\),但不會解決最後統計答案的經典問題,甚至想過用三維偏序,不過也確實能做就是了。要是會那個矩陣加單點詢問的掃描線就場切了。

不自己寫了,和題解思路一模一樣,但是維護 \(g_i\)\(lst_i\) 的手段不一樣。明天有時間就補和題解一樣的實現。

這份程式碼的前 190 行就是場上寫的。

#include <bits/stdc++.h>

using namespace std;

using ubt = long long;

inline int read() {
  int s = 0, w = 1;
  char c = getchar();
  while (!isdigit(c)) {
    if (c == '-') w = -1;
    c = getchar();
  }
  while (isdigit(c)) {
    s = s * 10 + c - 48;
    c = getchar();
  }
  return s * w;
}
inline void pr(int x) {
  if (x < 0) putchar('-'), x = -x;
  static int stk[20];
  int top = 0;
  do stk[++top] = x % 10, x /= 10; while (x);
  while (top) putchar(stk[top--] + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')

#define vec vector
#define eb emplace_back
#define bg begin
#define mkp make_pair
#define fi first
#define se second
using pii = pair<int, int>;
const int inf = 1e9;

const int maxN = 5e5 + 7;

int n, m;

struct node {
  int l, r;
  int hd, tl;
} a[maxN];

struct S1 {
  int t[maxN * 4], tg[maxN * 4];
#define ls (p * 2)
#define rs (p * 2 + 1)
  void make(int p, int v) {
    t[p] = tg[p] = v;
  }
  void down(int p) {
    if (!tg[p]) return;
    make(ls, tg[p]), make(rs, tg[p]);
    tg[p] = 0;
  }
  void cove(int L, int R, int v, int p, int l, int r) {
    if (L <= l && r <= R) return make(p, v);
    down(p);
    int mid = (l + r) / 2;
    if (L <= mid) cove(L, R, v, ls, l, mid);
    if (R > mid) cove(L, R, v, rs, mid + 1, r);
  }
  int ask(int K, int p = 1, int l = 1, int r = n) {
    if (l == r) return t[p];
    down(p);
    int mid = (l + r) / 2;
    return K <= mid ? ask(K, ls, l, mid) : ask(K, rs, mid + 1, r);
  }
#undef ls
#undef rs
} sg;

int du[maxN];

struct ques {
  int l, r, id;
} q[maxN];
vec<int> que[maxN];

int ans[maxN];

vec<tuple<int, int, int>> c[maxN];

int t[maxN], Lp;
void add(int x, int v) {
  for (; x <= Lp; x += x & -x)
    t[x] += v;
}
int ask(int x) {
  int res = 0;
  for (; x > 0; x -= x & -x)
    res += t[x];
  return res;
}
#define C(L, R, v) (add(L, v), add(R + 1, -v))

struct odt {
  int l;
  mutable int r, v;
  odt(int l = 0) : l(l) { r = v = 0; }
  odt(int _l, int _r, int _v) {
    l = _l, r = _r, v = _v;
  }
  friend bool operator < (const odt &A, const odt &B) {
    return A.l < B.l;
  }
};
set<odt> o;
auto split(int x) {
  if (x > n) return o.end();
  auto it = prev(o.upper_bound(odt(x)));
  if (it->l == x) return it;
  int l = it->l, r = it->r, v = it->v;
  return o.emplace(x, exchange(it->r, x - 1), it->v).first;
}
void assign(int l, int r, int v) {
  auto itr = split(r + 1), itl = split(l);
  for (auto i = itl; i != itr; i++)
    add(i->v, -1 * (i->r - i->l + 1));
  o.erase(itl, itr);
  o.emplace(l, r, v);
  add(v, r - l + 1);
}

int main() {
  //double st = clock();
  freopen("mo.in", "r", stdin);
  freopen("mo.out", "w", stdout);

  n = read(), m = read();
  Lp = m;
  for (int i = 1; i <= m; i++)
    a[i].l = read(), a[i].r = read();

  for (int i = 1; i <= m; i++) {
    a[i].hd = sg.ask(a[i].l);
    sg.cove(a[i].l, a[i].r, i, 1, 1, n);
  }
  sg.cove(1, n, m + 1, 1, 1, n);
  for (int i = m; i >= 1; i--) {
    a[i].tl = sg.ask(a[i].r);
    sg.cove(a[i].l, a[i].r, i, 1, 1, n);
  }

  static queue<int> qu;
  for (int i = 1; i <= m; i++)
    du[a[i].hd]++;
  for (int i = 1; i <= m; i++)
    if (du[i] == 0)
      qu.emplace(i);
  while (!qu.empty()) {
    int f = qu.front();
    qu.pop();
    auto t = a[f].hd;
    if (!t) continue;
    a[t].tl = max(a[t].tl, a[f].tl);
    if (--du[t] == 0)
      qu.emplace(t);
  }

  int Q = read();
  for (int i = 1; i <= Q; i++) {
    q[i].l = read(), q[i].r = read(), q[i].id = i;
    que[q[i].r].eb(i);
  }

  for (int i = 1; i <= m; i++)
    c[i].eb(a[i].hd + 1, i, 1),
    c[a[i].tl].eb(a[i].hd + 1, i, -1);

  for (int i = 1; i <= m; i++) {
    for (auto [l, r, v] : c[i])
      C(l, r, v);
    for (int j : que[i]) {
      auto t = q[j];
      ans[t.id] = ask(t.l);
    }
  }

  sort(q + 1, q + Q + 1, [](const ques &A, const ques &B) {
    return A.r < B.r;
  });
  memset(t, 0, sizeof t);
  Lp = m + 1;
  o.emplace(1, n, 1);
  add(1, n);
  int now = 0;
  for (int i = 1; i <= Q; i++) {
    while (now < q[i].r) {
      now++;
      assign(a[now].l, a[now].r, now + 1);
    }
    ans[q[i].id] += ask(q[i].l);
  }

  for (int i = 1; i <= Q; i++)
    pr(ans[i]), end_;

  //double ed = clock();
  //cerr << (ed - st) / CLOCKS_PER_SEC << '\n';
}