邮寄
菜到不能再菜的 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
),并在集合大小 \(\ge B\) 时把 set
里面的所有节点全部分为一个省,省会为当前节点。
可以证明这样一定可以构造出来(省大小 \(\le 2 * B\))。
#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;
}
标签:10.0,cnt,int,sum,DFS,st,dp
From: https://www.cnblogs.com/leavenothingafterblog/p/18446032/speedrunv10