《如 何 速 通 一 套 题》 10.0

邮寄

菜到不能再菜的 hhc 一个题都不会,光速撤退了。

A

nm 没想到只要 S 中有一种数出现了奇数次 C 必胜。

然后直接 xorhash 就可以了。

#include <bits/stdc++.h>
#define int unsigned long long
using namespace std;
struct node {
int v, w;
};
int t, n, u, v, w, d[500050], ans;
vector<node> to[500050];
map<int, int> cnt;
int qpow(int x, int y) {
int rs = 1;
for(; y; y >>= 1) {
if(y & 1) {
rs *= x;
}
x *= x;
}
return rs;
}
void DFS(int x = 1, int pa = 0) {
cnt[d[x]]++;
for(auto i : to[x]) {
if(i.v != pa) {
d[i.v] = d[x] ^ qpow(11451, i.w);
DFS(i.v, x);
}
}
}
signed main() {
freopen("game.in", "r", stdin);
freopen("game.out", "w", stdout);
for(cin >> t; t--; ) {
cin >> n;
for(int i = 1; i < n; i++) {
cin >> u >> v >> w;
to[u].push_back({v, w});
to[v].push_back({u, w});
}
DFS();
ans = n * (n - 1) / 2;
for(auto i : cnt) {
ans -= i.second * (i.second - 1) / 2;
}
cout << ans << '\n';
for(int i = 1; i <= n; i++) {
to[i].clear();
d[i] = 0;
}
cnt.clear();
}
return 0;
}

B 跳跃

我们充分发挥人类智慧,猜测答案一定会在前 5000 轮内更新完。

直接暴力 dp 即可。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int kInf = 1e17;
int t, n, k, dp[1010], arr[1010], sum[1010], ml[1010], mr[1010];
signed main() {
freopen("jump.in", "r", stdin);
freopen("jump.out", "w", stdout);
for(cin >> t; t--; ) {
cin >> n >> k;
for(int i = 1; i <= n; i++) {
cin >> arr[i];
sum[i] = sum[i - 1] + arr[i];
}
int m = 0;
for(int i = 1; i <= n; i++) {
ml[i] = sum[i] - m;
m = min(m, sum[i]);
}
m = -kInf;
for(int i = n; i >= 1; i--) {
m = max(m, sum[i]);
mr[i] = m - sum[i - 1];
}
fill(dp + 1, dp + n + 1, -kInf);
dp[1] = 0;
int ans = 0;
for(int i = 1; i <= min(k, 5000ll); i++) {
if(i & 1) {
int mx = -kInf;
for(int j = 1; j <= n; j++) {
mx = max(mx, dp[j] - sum[j - 1]);
dp[j] = mx + sum[j];
if(dp[j] < 0) {
dp[j] = -kInf;
}
ans = max(ans, dp[j] + (k - i) * ml[j]);
}
}else {
int mx = -kInf;
for(int j = n; j >= 1; j--) {
mx = max(mx, dp[j] + sum[j]);
dp[j] = mx - sum[j - 1];
if(dp[j] < 0) {
dp[j] = -kInf;
}
ans = max(ans, dp[j] + (k - i) * mr[j]);
}
}
}
cout << ans << '\n';
}
return 0;
}

C 大陆

可以观察到每一个省要么是一个连通块,要么加上一个省会后变成连通块。

所以我们 DFS,并且启发式合并维护每一个点上还没有分好省的节点的集合(开一个 set),并在集合大小 B 时把 set 里面的所有节点全部分为一个省,省会为当前节点。

可以证明这样一定可以构造出来(省大小 2B)。

#include <bits/stdc++.h>
using namespace std;
int n, k, u, v, fs[10010], cnt, bel[10010];
vector<int> to[10010], ps[10010];
set<int> st[10010];
void trigger(int x) {
if(st[x].size() >= k) {
cnt++;
for(auto i : st[x]) {
//ps[cnt].push_back(i);
bel[i] = cnt;
}
fs[cnt] = x;
st[x].clear();
}
}
void DFS(int x = 1, int pa = 0) {
for(auto i : to[x]) {
if(i != pa) {
DFS(i, x);
if(st[x].size() < st[i].size()) {
swap(st[x], st[i]);
}
for(auto j : st[i]) {
st[x].insert(j);
}
st[i].clear();
trigger(x);
}
}
st[x].insert(x);
trigger(x);
}
int main() {
freopen("mainland.in", "r", stdin);
freopen("mainland.out", "w", stdout);
cin >> n >> k;
for(int i = 1; i < n; i++) {
cin >> u >> v;
to[u].push_back(v);
to[v].push_back(u);
}
DFS();
cout << cnt << '\n';
for(int i = 1; i <= n; i++) {
cout << bel[i] << ' ';
}
cout << '\n';
for(int i = 1; i <= cnt; i++) {
cout << fs[i] << ' ';
}
cout << '\n';
return 0;
}
posted @   hhc0001  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示