CF 1939 B
题目描述
有一些点和 \(N-1\) 次操作,每次会在点 \(u\) 上所有纸条的上方贴一张纸条 \(c_u\),在 \(v\) 上贴 \(c_v\),并在两个点之间建一条边权为 \(w_{u,v}\) 的边,这次操作必须满足 \(c_u+c_v\ge w_{u,v}\)。
现在给你每个点上从上至下的纸条和所有边的边权,请给出一种加边方案或确定方案不存在。
思路
我们考虑从叶子结点一步一步贪心地往上推。我们可以从叶子结点开始,对于每个儿子找到最小的可以满足地纸条并使用即可。
空间复杂度 \(O(N)\),时间复杂度 \(O(N\log N)\)。
代码
#include<bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
const int MAXN = 200001;
int n, q, d[MAXN], fid[MAXN];
vector<int> a[MAXN];
set<pii> s[MAXN];
vector<tuple<int, int, int>> e[MAXN];
vector<pii> edge;
void dfs(int u, int fa) {
a[u].resize(e[u].size());
for(auto [v, w, id] : e[u]) {
if(v != fa) {
fid[v] = id;
dfs(v, u);
auto it = s[u].lower_bound({w - s[v].begin()->first, 0});
if(it == s[u].end()) {
cout << "No";
exit(0);
}
a[u][it->second] = id;
s[u].erase(it);
}
}
}
void DFS(int u) {
for(int x : a[u]) {
if(!x) {
cout << fid[u] << " ";
}else {
DFS(edge[x - 1].first == u ? edge[x - 1].second : edge[x - 1].first);
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> q;
for(int i = 1, u, v, w; i < n; ++i) {
cin >> u >> v >> w;
e[u].emplace_back(v, w, i);
e[v].emplace_back(u, w, i);
edge.emplace_back(u, v);
d[u]++, d[v]++;
}
for(int i = 1; i <= n; ++i) {
for(int j = 1, x; j <= d[i]; ++j) {
cin >> x;
s[i].insert({x, d[i] - j});
}
}
dfs(1, 0);
cout << "Yes\n";
DFS(1);
return 0;
}
CF 1939 C
题目描述
有 \(k\) 个一模一样地栈,每个栈的第 \(i\) 个元素是一个种类为 \(A_i\) 的礼物。有若干个人,每个人都可以拿若干个礼物,只有拿完了前一个栈中的礼物,才能拿下一个栈的,并且只能从栈顶拿。但每个人拿的不同种类礼物数量不能超过 \(t\) 个,求至少要多少个人才能把礼物拿完。
思路
很明显一个人会拿所有能拿的,所以我们可以用双指针预处理出从每个礼物开始拿会拿到哪个礼物。使用倍增求解即可。
时空复杂度均为 \(O(N\log N)\)。
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 600001;
int n, k, t, a[MAXN], tot, cnt[MAXN], f[61][MAXN];
ll g[61][MAXN], ans;
vector<int> ve;
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k >> t;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
ve.emplace_back(a[i]);
}
sort(ve.begin(), ve.end()), ve.erase(unique(ve.begin(), ve.end()), ve.end());
if(t >= ve.size()) {
cout << 1;
return 0;
}
for(int i = 1; i <= n; ++i) {
a[i] = lower_bound(ve.begin(), ve.end(), a[i]) - ve.begin() + 1;
if(a[i] != a[tot]) {
a[++tot] = a[i];
}
}
for(int i = 1; i <= tot; ++i) {
a[tot + i] = a[i];
}
int res = 0;
for(int i = 1, j = 1; i <= tot; --cnt[a[i]], res -= !cnt[a[i]], ++i) {
for(; j <= 2 * tot && res + !cnt[a[j]] <= t; res += !cnt[a[j]], ++cnt[a[j++]]) {
}
f[0][i] = (j > tot ? j - tot : j);
g[0][i] = (j > tot);
}
for(int i = 1; i <= 60; ++i) {
for(int j = 1; j <= tot; ++j) {
f[i][j] = f[i - 1][f[i - 1][j]];
g[i][j] = g[i - 1][j] + g[i - 1][f[i - 1][j]];
}
}
int x = 1;
ll pos = 1;
for(int i = 60; i >= 0; --i) {
if(pos + g[i][x] <= k) {
pos += g[i][x], x = f[i][x], ans += (1ll << i);
}
}
res = 0;
for(int i = 1; i <= n; ++i) {
cnt[i] = 0;
}
for(int i = x, j = x; i <= tot; i = j) {
for(; j <= tot && res + !cnt[a[j]] <= t; res += !cnt[a[j]], ++cnt[a[j++]]) {
}
ans++;
res = 0;
for(int p = i; p < j; ++p) {
cnt[a[p]] = 0;
}
}
cout << ans;
return 0;
}
标签:cout,int,OOI,MAXN,using,礼物,XVIII,ve
From: https://www.cnblogs.com/yaosicheng124/p/18487893