2024初秋集训——提高组 #32
B. 序列删除
题目描述
有一个长度为
思路
有一个很显然的贪心就是:每次取代价最小的两个数删除。所以我们按照代价排序,用树状数组维护区间中未被删除的数的数量即可。
空间复杂度
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200001, MAXV = (1 << 20);
struct Node {
int l, r;
}s[MAXN];
int n, a[MAXN], l[MAXN], tr[MAXN];
ll ans;
void update(int p, int x) {
for(; p <= 2 * n; tr[p] += x, p += (p & -p)) {
}
}
int Getsum(int p) {
int sum = 0;
for(; p; sum += tr[p], p -= (p & -p)) {
}
return sum;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n;
for(int i = 1; i <= 2 * n; ++i) {
cin >> a[i];
if(!l[a[i]]) {
l[a[i]] = i;
}else {
s[a[i]] = {l[a[i]], i};
}
}
sort(s + 1, s + n + 1, [](const Node &a, const Node &b) -> bool {
return a.r - a.l < b.r - b.l;
});
for(int i = 1; i <= n; ++i) {
ans += s[i].r - s[i].l - Getsum(s[i].r) + Getsum(s[i].l);
update(s[i].l, 1), update(s[i].r, 1);
}
cout << ans;
return 0;
}
C. 史莱姆融合
题目描述
在一棵
- 如果一只史莱姆通过了边权为
的边,则其体积减 。若其体积变为非正数,则其消失。 - 如果多只史莱姆待在同一个结点,则它们将会合并为体积为其体积之和的史莱姆。
- 史莱姆最终都要到达一个结点
,但它们会按最优方案行动。
有
思路
我们先只考虑
接着我们考虑换根,
空间复杂度
代码
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
const int MAXN = 100001;
const ll INF = (ll)(1e18);
int n, k, q, a[MAXN], son[MAXN];
ll dp[3][MAXN];
vector<pii> e[MAXN];
void dfs(int u, int fa) {
dp[0][u] = a[u];
for(pii g : e[u]) {
int v = g.first, w = g.second;
if(v != fa) {
dfs(v, u);
dp[0][u] += max(0ll, dp[0][v] - w);
}
}
dp[1][u] = dp[0][u] - a[u], dp[2][u] = INF, son[u] = u;
for(pii g : e[u]) {
int v = g.first, w = g.second;
if(v != fa) {
ll x = dp[0][u] - max(0ll, dp[0][v] - w) + max(0ll, dp[1][v] - w);
if(x < dp[1][u]) {
dp[2][u] = dp[1][u], dp[1][u] = x, son[u] = v;
}else if(x < dp[2][u]) {
dp[2][u] = x;
}
}
}
}
void DFS(int u, int fa) {
for(pii g : e[u]) {
int v = g.first, w = g.second;
if(v != fa) {
ll v0 = dp[0][v], u0 = dp[0][u] - max(0ll, v0 - w);
dp[0][v] += max(0ll, u0 - w);
dp[1][v] += max(0ll, u0 - w);
dp[2][v] += max(0ll, u0 - w);
if(son[u] != v) {
ll x = dp[0][v] - max(0ll, u0 - w) + max(0ll, dp[1][u] - max(0ll, v0 - w) - w);
if(x < dp[1][v]) {
dp[2][v] = dp[1][v], dp[1][v] = x, son[v] = u;
}else if(x < dp[2][v]) {
dp[2][v] = x;
}
}else {
ll x = dp[0][v] - max(0ll, u0 - w) + max(0ll, dp[2][u] - max(0ll, v0 - w) - w);
if(x < dp[1][v]) {
dp[2][v] = dp[1][v], dp[1][v] = x, son[v] = u;
}else if(x < dp[2][v]) {
dp[2][v] = x;
}
}
DFS(v, u);
}
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k >> q;
for(int i = 1, u, v, w; i < n; ++i) {
cin >> u >> v >> w;
e[u].emplace_back(v, w);
e[v].emplace_back(u, w);
}
for(int i = 1, u; i <= k; ++i) {
cin >> u >> a[u];
}
dfs(1, 0);
DFS(1, 0);
for(int i = 1, u, v; i <= q; ++i) {
cin >> u >> v;
cout << dp[v][u] << "\n";
}
return 0;
}
本文作者:yaosicheng124
本文链接:https://www.cnblogs.com/yaosicheng124/p/18450473
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步