AGC018
AGC018
B
题目大意
举办一场运动会,有
解题思路
考虑贪心。
一开始,我们不妨开设所有项目,设人数最多的项目为
如果我们不关闭项目 vector
存储参加这个项目的人)。
于是,又会有新的人数最多的项目,我们重复这个过程,直到只剩下一个项目,期间最大值的最小值即为答案。
注意:在重新分配项目时,不仅要根据次高排名,还要判断这个项目现在是否开设,不开设还要再往后。
时间复杂度:
代码
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
const int N = 310;
int n, m, ans;
int a[N][N], b[N][N], sz[N];
vector<int> e[N];
bool vis[N];
inline void add(int u, int v)
{
e[u].push_back(v);
sz[u]++;
}
int main()
{
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> a[i][j];
b[i][a[i][j]] = j;
if (j == 1)
{
add(a[i][j], i);
}
}
}
for (int i = 1; i <= m; i++)
{
if (!vis[i])
{
ans = max(sz[i], ans);
}
}
for (int i = 1; i < m; i++)
{
int x = 0, mx = 0;
for (int i = 1; i <= m; i++)
{
if (!vis[i])
{
if (sz[i] > mx)
{
mx = sz[i];
x = i;
}
}
}
ans = min(mx, ans);
for (auto it : e[x])
{
int v = b[it][x] + 1;
while (vis[a[it][v]])
{
v++;
}
add(a[it][v], it);
}
vis[x] = 1;
}
cout << ans << endl;
return 0;
}
C
题目大意
有
要选出
解题思路
考虑反悔贪心。
一开始有三个元素:金币、银币、铜币,较难处理。
考虑反悔机制,直接默认所有人都拿金币,之后把
具体地,把金币个数加到答案里,再把每个人的信息改成二元组
记
考虑何时
即
于是我们可以按
然后可以用优先队列维护前缀最大的
答案即为:
时间复杂度
代码
#include<bits/stdc++.h>
#define endl "\n"
#define ll long long
using namespace std;
const int N = 1e5 + 10;
struct node
{
int a, b;
} p[N];
int n, x, y, z;
ll ans, s[N], t[N];
priority_queue<ll, vector<ll>, greater<ll> > q;
bool cmp(node x, node y)
{
return x.a - x.b > y.a - y.b;
}
int main()
{
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> x >> y >> z;
n = x + y + z;
for (int i = 1; i <= n; i++)
{
int a, b, c;
cin >> a >> b >> c;
ans += a;
p[i].a = b - a, p[i].b = c - a;
}
sort(p + 1, p + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
s[i] = s[i - 1] + p[i].a;
q.push(p[i].a);
if ((int)q.size() > y)
{
s[i] -= q.top();
q.pop();
}
}
while (!q.empty())
{
q.pop();
}
for (int i = n; i >= 1; i--)
{
t[i] = t[i + 1] + p[i].b;
q.push(p[i].b);
if ((int)q.size() > z)
{
t[i] -= q.top();
q.pop();
}
}
ll mx = LONG_LONG_MIN;
for (int i = y; i <= n - z; i++)
{
mx = max(mx, s[i] + t[i + 1]);
}
cout << ans + mx << endl;
return 0;
}
D
题目大意
给出一棵有
解题思路
先考虑最长哈密顿回路长度。
要使其最长,就需要尽可能多地经过每一条边,考虑树上一条边能做出的最大贡献。
设这条边为
考虑能否让每条边取到这个上界,假设子树的点数小于子树外点数,可以发现取到上界时不能有路径在子树内部,因为子树点数本来就少,又被自己匹配掉一些,就会使经过这条边的最大次数减少,如果大于同理,也不能有路径完全在子树外。
为了方便讨论,我们不妨钦定重心为树根(如果重心有两个就可以缩点成一个),根据重心的性质,不会有子树点数大于子树外点数的情况,就避免了考虑另一种情况。
于是可以得到:不能有路径在一个子树内部,即每条路径都要经过重心,就可以取到最值(补充:一个重心可以就只在达重心上,两个重心必须经过连接两个重心的边),我们只需将答案加上最值即可。
现在我们考虑哈密顿路径,就是在回路的基础上减去一条最短的路径。
- 一个重心:此时最小值一定是在终点在重心上,那么就可以钦定连接重心的最小边为最后一条边,删去它损失必定最小
- 两个重心:由于两个重心必须经过连接两个重心的边,那么最短的路径即恰好为连接两个重心的边。
时间复杂度:
关于讨论区问题的补充:
证明最大哈密顿回路去掉最小边一定是最大哈密顿路径。
如果它不是最大哈密顿回路,即存在在同一棵子树的路径,由于一条路径会匹配掉两个点,那么就会使得经过的连接重心的边的访问次数减
如图,中间的边少访问了两次:(非原创,侵删)
因为少了两次,而我们的哈密顿路径选取了最小的边,只少一次,因此它的哈密顿回路已经小于最大的哈密顿路径,所以哈密顿路径更小于最大的哈密顿路径。
代码
#include<bits/stdc++.h>
#define endl "\n"
#define ll long long
using namespace std;
const int N = 1e5 + 10;
struct edge
{
int to, w, next;
} e[N << 1];
ll n, tot, ans, p1, p2;
ll h[N], sz[N], mx[N];
void add(int u, int v, int w)
{
tot++;
e[tot].to = v;
e[tot].w = w;
e[tot].next = h[u];
h[u] = tot;
}
void dfs(int u, int fa)
{
sz[u] = 1;
for (int i = h[u]; i; i = e[i].next)
{
int v = e[i].to;
if (v == fa)
{
continue;
}
dfs(v, u);
sz[u] += sz[v];
mx[u] = max(mx[u], sz[v]);
ans += 2 * min(sz[v], n - sz[v]) * e[i].w;
}
mx[u] = max(mx[u], n - sz[u]);
}
int main()
{
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i < n; i++)
{
int u, v, w;
cin >> u >> v >> w;
add(u, v, w), add(v, u, w);
}
dfs(1, 0);
ll mn = LONG_LONG_MAX;
for (int i = 1; i <= n; i++)
{
mn = min(mn, mx[i]);
}
for (int i = 1; i <= n; i++)
{
if (mx[i] == mn)
{
if (!p1)
{
p1 = i;
}
else
{
p2 = i;
}
}
}
mn = LONG_LONG_MAX;
for (int i = h[p1]; i; i = e[i].next)
{
int v = e[i].to;
if (p2 && v != p2)
{
continue;
}
mn = min(mn, (ll)e[i].w);
}
cout << ans - mn << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)