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';
}