82 lines
2.7 KiB
Text
82 lines
2.7 KiB
Text
---
|
|
id: springboards
|
|
title: "Max Suffix Query with Insertions Only"
|
|
author: Benjamin Qi
|
|
prerequisites:
|
|
- Silver - More with Maps & Sets
|
|
- Silver - Amortized Analysis
|
|
description: "A solution to USACO Gold - Springboards."
|
|
frequency: 1
|
|
---
|
|
|
|
import { Problem } from "../models";
|
|
|
|
export const metadata = {
|
|
problems: {
|
|
sample: [
|
|
new Problem("Gold", "Springboards", "995", "Hard", false, [], ""),
|
|
],
|
|
problems: [
|
|
new Problem("Plat", "Nocross", "721", "Hard", false, [], ""),
|
|
new Problem("CF", "Karen & Cards", "contest/815/problem/D", "Very Hard", false, [], "For each a from p to 1, calculate the number of possible cards with that value of a."),
|
|
new Problem("CF", "GP of Korea 19 - Interesting Drug", "gym/102059/problem/K", "Very Hard", false, [], "Genfuncs not required but possibly helpful"),
|
|
]
|
|
}
|
|
};
|
|
|
|
<problems-list problems={metadata.problems.sample} />
|
|
|
|
<br/>
|
|
|
|
To solve this problem, we need a data structure that supports operations similar to the following:
|
|
|
|
1. Add a pair $(a,b)$.
|
|
2. For any $x$, query the maximum value of $b$ over all pairs satisfying $a\ge x$.
|
|
|
|
This can be solved with a **segment tree** (see "Point Update Range Sum"), but a simpler option is to use a map. We rely on the fact
|
|
that if there exist pairs $(a,b)$ and $(c,d)$ in the map such that $a\le c$ and $b\le d$, we can simply ignore $(a,b)$ (and the answers to future queries will not be affected). So at every point in time, the pairs $(a_1,b_1),(a_2,b_2),\ldots,(a_k,b_k)$ that we store in the map will satisfy $a_1 < a_2 < \cdots < a_k$ and $b_1 > b_2 > \cdots > b_k$.
|
|
|
|
- Querying for a certain $x$ can be done with a single `lower_bound` operation, as we just want the minimum $i$ such that $a_i\ge x$.
|
|
- When adding a pair $(a',b')$, first check if there exists $(a,b)$ already in the map such that $a\ge a', b\ge b'$.
|
|
- If so, then do nothing.
|
|
- Otherwise, insert $(a',b')$ into the map and repeatedly delete pairs $(a,b)$ such that $a\le a', b\le b'$ from the map until none remain.
|
|
|
|
If there are $N$ insertions, then each query takes $O(\log N)$ time and adding a pair takes $O(\log N)$ time amortized.
|
|
|
|
<LanguageSection>
|
|
|
|
<CPPSection>
|
|
|
|
```cpp
|
|
#define f first
|
|
#define s second
|
|
#define lb lower_bound
|
|
|
|
map<int,ll> m;
|
|
void ins(int a, ll b) {
|
|
auto it = m.lb(a); if (it != end(m) && it->s >= b) return;
|
|
it = m.insert(it,{a,b}); it->s = b;
|
|
while (it != begin(m) && prev(it)->s <= b) m.erase(prev(it));
|
|
}
|
|
ll query(int x) { auto it = m.lb(x);
|
|
return it == end(m) ? 0 : it->s; }
|
|
// it = end(m) means that no pair satisfies a >= x
|
|
```
|
|
|
|
</CPPSection>
|
|
|
|
<JavaSection>
|
|
|
|
|
|
|
|
</JavaSection>
|
|
|
|
</LanguageSection>
|
|
|
|
## Problems
|
|
|
|
(easier examples?)
|
|
|
|
<IncompleteSection />
|
|
|
|
<problems-list problems={metadata.problems.problems} />
|