题解 QOJ2559【Endless Road】/ SS241006D【套路题】
Petrozavodsk Winter 2022. Day 2. KAIST Contest + KOI TST 2021
XXII Open Cup named after E.V. Pankratiev, Grand Prix of Daejeon
题目描述
现在有
给定
-
设当前第
个二元组的权值是满足花盆 为空且 的 数量。选出未被选过且权值最小的二元组 。如果存在多个权值最小的二元组,选择其中编号最小的。 -
对于
,在花盆 中种上花。
请求出每次操作选择出的二元组
保证对于
对于所有数据,
solution
改成左闭右开。离散化。跳过一些暴力后,我们发现:两个互相包含的区间
剩下的问题是删除一个合法区间后怎么找到新的合法区间。我们将所有区间按照右端点升序为第一关键字,左端点降序为第二关键字,以及自身编号升序为第三关键字,对所有区间进行排序,使每个区间获得一个排名。这样排序后,两个互相包含的区间
用另一棵线段树将所有非法区间存放在线段树上它们各自排名的位置,每次删除区间时,记删除的区间的排名为
至此可以在
code
需要开两棵线段树,支持的线段树二分都有所不同。找 std::set
,因为合法区间按照排名、或者左端点、或者右端点排序的结果都是一样的,可以随便写。插入新的合法区间时需要知晓其权值,使用另一个树状数组维护。seg1
是合法区间,seg2
是非法区间。
#include <bits/stdc++.h>
using namespace std;
#ifdef LOCAL
#define debug(...) ((void)fprintf(stderr, ##__VA_ARGS__))
#else
#define endl "\n"
#define debug(...) ((void)0)
#endif
using LL = long long;
template <int N, class T>
struct fenwick {/*{{{*/
T c[N + 10];
fenwick() { memset(c, 0, sizeof c); }
void add(int p, T k) { for (; p <= N; p += p & -p) c[p] += k; }
T qry(int p) { T r = 0; for (; p >= 1; p -= p & -p) r += c[p]; return r; }
};/*}}}*/
template <class T>
struct flower {/*{{{*/
vector<T> vec;
template <class U> flower& operator<<(U&& x) {
vec.push_back(forward<U>(x));
return *this;
}
size_t build() {
auto bg = vec.begin(), ed = vec.end();
sort(bg, ed);
vec.erase(unique(bg, ed), ed);
return vec.size();
}
size_t operator()(const T& x) const {
return lower_bound(vec.begin(), vec.end(), x) - vec.begin();
}
T operator[](int i) const { return vec[i]; }
};/*}}}*/
struct range {
int l, r, id;
} a[250010];
int n, m, nxt[500010], wh[500010];
int findnxt(int x) { return nxt[x] == x ? x : nxt[x] = findnxt(nxt[x]); }
flower<int> hua;
fenwick<500010, int> fen;
set<int> st;
namespace seg2 {
constexpr int N = 2.5e5;
int maxl[N << 2];
void maintain(int p) { maxl[p] = max(maxl[p << 1], maxl[p << 1 | 1]); }
void build(int p, int l, int r) {/*{{{*/
if (l == r) {
maxl[p] = -1e9;
return ;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
maintain(p);
}/*}}}*/
void setValue(int x, int v, int p, int l, int r) {/*{{{*/
if (l == r) {
maxl[p] = v;
return ;
}
int mid = (l + r) >> 1;
if (x <= mid) setValue(x, v, p << 1, l, mid);
else setValue(x, v, p << 1 | 1, mid + 1, r);
maintain(p);
}/*}}}*/
int binary(int L, int R, int v, int p, int l, int r) {
if (L <= l && r <= R) {
if (maxl[p] <= v) return n + 1;
if (l == r) return l;
}
int mid = (l + r) >> 1;
int ret = L <= mid ? binary(L, R, v, p << 1, l, mid) : n + 1;
if (ret <= n) return ret;
return mid < R ? binary(L, R, v, p << 1 | 1, mid + 1, r) : n + 1;
}
void enable(int id) { debug("seg2::enable(%d)\n", a[id].id); setValue(id, a[id].l, 1, 1, n); }
void disable(int id) { debug("seg2::disable(%d)\n", a[id].id); setValue(id, -1e9, 1, 1, n); }
};
namespace seg1 {
constexpr int N = 5e5;
pair<int, int> ans[N << 2];
int tag[N << 2], maxr[N << 2];
void maintain(int p) {
ans[p] = min(ans[p << 1], ans[p << 1 | 1]);
maxr[p] = max(maxr[p << 1], maxr[p << 1 | 1]);
}
void spread(int p, int k) { ans[p].first -= k, tag[p] += k; }
void pushdown(int p) { spread(p << 1, tag[p]), spread(p << 1 | 1, tag[p]), tag[p] = 0; }
void build(int p, int l, int r) {/*{{{*/
tag[p] = 0;
if (l == r) {
ans[p] = make_pair(1e9, -1);
maxr[p] = -1e9;
return ;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid);
build(p << 1 | 1, mid + 1, r);
maintain(p);
}/*}}}*/
void setValue(int x, int id, int p, int l, int r) {/*{{{*/
if (l == r) {
if (id > 0) {
int len = hua[a[id].r - 1] - hua[a[id].l - 1];
int lenp = fen.qry(a[id].r - 1) - fen.qry(a[id].l - 1);
ans[p] = make_pair(len - lenp, a[id].id);
maxr[p] = a[id].r;
} else {
ans[p] = make_pair(1e9, -1);
maxr[p] = -1e9;
}
return ;
}
int mid = (l + r) >> 1;
pushdown(p);
if (x <= mid) setValue(x, id, p << 1, l, mid);
else setValue(x, id, p << 1 | 1, mid + 1, r);
maintain(p);
}/*}}}*/
void modify(int L, int R, int k, int p, int l, int r) {/*{{{*/
if (L <= l && r <= R) return spread(p, k);
int mid = (l + r) >> 1;
pushdown(p);
if (L <= mid) modify(L, R, k, p << 1, l, mid);
if (mid < R) modify(L, R, k, p << 1 | 1, mid + 1, r);
maintain(p);
}/*}}}*/
void enable(int id) {
debug("seg1::enable(%d) = [%d, %d]\n", a[id].id, a[id].l, a[id].r);
st.insert(id);
setValue(a[id].l, id, 1, 1, m);
}
void disable(int id) {
debug("seg1::disable(%d) = [%d, %d]\n", a[id].id, a[id].l, a[id].r);
assert(st.find(id) != st.end());
auto it = st.erase(st.find(id));
int t = it == st.begin() ? 0 : a[*prev(it)].l;
int q = it == st.end() ? n + 1 : *it;
setValue(a[id].l, -1, 1, 1, m);
int y = seg2::binary(id, n, t, 1, 1, n);
while (y < q) {
enable(y);
seg2::disable(y);
t = a[y].l;
y = seg2::binary(id, n, t, 1, 1, n);
}
}
int binary(int L, int R, int v, int p, int l, int r) {
if (L <= l && r <= R) {
if (maxr[p] <= v) return m + 1;
if (l == r) return l;
}
int mid = (l + r) >> 1;
pushdown(p);
int ret = L <= mid ? binary(L, R, v, p << 1, l, mid) : m + 1;
if (ret <= m) return ret;
return mid < R ? binary(L, R, v, p << 1 | 1, mid + 1, r) : m + 1;
}
void plant(int pos) {
debug("plant(pos = %d)\n", pos);
// forall range, l <= pos < r
int len = hua[pos] - hua[pos - 1]; // hua[], 0-indexed
fen.add(pos, len);
int res = binary(1, pos, pos, 1, 1, m);
if (res <= pos) modify(res, pos, len, 1, 1, m);
}
int qrymax() { return wh[ans[1].second]; }
};
int main() {
#ifndef LOCAL
#ifndef NF
freopen("ds.in", "r", stdin);
freopen("ds.out", "w", stdout);
#endif
cin.tie(nullptr)->sync_with_stdio(false);
#endif
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i].l >> a[i].r, a[i].id = i, hua << a[i].l << a[i].r;
m = (int)hua.build();
for (int i = 1; i <= n; i++) a[i].l = (int)hua(a[i].l) + 1;
for (int i = 1; i <= n; i++) a[i].r = (int)hua(a[i].r) + 1;
auto key = [](auto&& self) { return make_tuple(self.r, -self.l, self.id); };
sort(a + 1, a + n + 1, [&](auto&& lhs, auto&& rhs) { return key(lhs) < key(rhs); }); // std::forward /lh
for (int i = 1; i <= n; i++) wh[a[i].id] = i;
for (int i = 1; i <= m; i++) nxt[i] = i;
seg1::build(1, 1, m);
seg2::build(1, 1, n);
for (int i = 1; i <= n; i++) {
if (st.empty() || a[*st.rbegin()].l < a[i].l) seg1::enable(i);
else seg2::enable(i);
}
for (int t = 1; t <= n; t++) {
int pos = seg1::qrymax();
cout << a[pos].id << " \n"[t == n];
int now = findnxt(a[pos].l);
while (now < a[pos].r) {
seg1::plant(now);
nxt[now] = now + 1;
now = findnxt(now);
}
seg1::disable(pos);
#ifdef LOCAL
for (int x : st) debug("%d ", a[x].id);
debug("\n");
for (int x : st) debug("[%d, %d] ", a[x].l, a[x].r);
debug("\n");
#endif
}
return 0;
}
本文来自博客园,作者:caijianhong,转载请注明原文链接:https://www.cnblogs.com/caijianhong/p/18450510/solution-SS241006D
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2023-10-07 题解 CPOJ::master 62【图的计数】
2023-10-07 题解 SS231007A【运输 (transport)】
2023-10-07 题解 AGC015D【A or...or B Problem】