题解:P13520 [KOI 2025 #2] 存放箱子
我们要把
可以把两个数组的配对抽象成一个括号序列的括号配对。将
可以拿样例举例。考虑一下如下输入数据:
6 4
5 1
9 8
2 1
变成括号序列之后变成
[1:]))[2:]([4:])[5:]([6:]([8:])[9:](
))()(()(
总共有
考虑将
#include <bits/stdc++.h>
using namespace std;
const int N = 4e5 + 7;
int n;
pair<int, int> p[N];
map<int, int> mp;
struct node {
int l, r, mid, sum, lk, rk;
}tr[N << 2];
void build(int p, int l, int r) {
tr[p].l = l, tr[p].r = r;
tr[p].mid = l + r >> 1;
tr[p].sum = 0; tr[p].lk = 0, tr[p].rk = 0;
if(l == r) return ;
build(p << 1, l, tr[p].mid);
build(p << 1 | 1, tr[p].mid + 1, r);
}
void push_up(node &rt, node lft, node rgt) {
rt.sum = lft.sum + rgt.sum + min(lft.lk, rgt.rk);
rt.lk = lft.lk + rgt.lk - min(lft.lk, rgt.rk);
rt.rk = lft.rk + rgt.rk - min(lft.lk, rgt.rk);
}
void upd(int p, int x, int tp) {
if(tr[p].l == tr[p].r) {
if(tp == 1) tr[p].lk ++;
else tr[p].rk ++;
if(tr[p].lk && tr[p].rk) {
tr[p].lk --, tr[p].rk --;
tr[p].sum ++;
}
return ;
}
if(x <= tr[p].mid) upd(p << 1, x, tp);
else upd(p << 1 | 1, x, tp);
push_up(tr[p], tr[p << 1], tr[p << 1 | 1]);
}
int main() {
ios :: sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++) {
cin >> p[i].first >> p[i].second;
mp[p[i].first] = 1, mp[p[i].second] = 1;
}
int cnt = 0;
for(auto &tmp : mp) tmp.second = ++ cnt;
build(1, 1, cnt);
for(int i = 1; i <= n; i ++) {
p[i].first = mp[p[i].first];
p[i].second = mp[p[i].second];
upd(1, p[i].first, 1);
upd(1, p[i].second, 2);
cout << i - tr[1].sum << '\n';
}
return 0;
}