Codeforces Round #635 (Div. 2)
https://codeforces.com/contest/1337
雀魂场又来啦。
A - Ichihime and Triangle
随便弄弄。
B - Kana and Dragon Quest game
随便弄弄。
C - Linova and Kingdom
首先可以得到一个观察:根必定是旅游城市,离根最远的叶子必定是工业城市。
第二个观察:若某个节点是工业城市,则其子树都是工业城市。(否则,选择其子树的一个旅游城市和其交换,答案只会更好)
每个节点维护其子树的大小,那么某个节点变成工业城市的收益就是“其到根的距离”减去“其子树的大小-1”。
vector<int> G[200005];
int pa[200005];
int de[200005];
int siz[200005];
int cnt[200005];
priority_queue<pii> PQ;
void dfs(int u, int p, int d) {
pa[u] = p;
de[u] = d;
siz[u] = 1;
cnt[u] = 0;
for(auto &v : G[u]) {
if(v == p)
continue;
dfs(v, u, d + 1);
siz[u] += siz[v];
cnt[u] += 1;
}
if(cnt[u] == 0)
PQ.push({d, u});
return;
}
void TestCase() {
int n, k;
scanf("%d%d", &n, &k);
for(int i = 1; i <= n - 1; ++i) {
int u, v;
scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1, -1, 0);
ll sum = 0;
while(k--) {
sum += PQ.top().first;
//printf("u=%d \n", PQ.top().second);
int p = pa[PQ.top().second];
PQ.pop();
cnt[p] -= 1;
if(cnt[p] == 0)
PQ.push({de[p] - siz[p] + 1, p});
}
printf("%lld\n", sum);
return;
}
现在的C题都这么复杂了吗?题解好像是直接排序或者nth_element,而不管它是不是叶子。
D - Xenia and Colorful Gems
假如枚举一个宝石作为“核心”,另外两颗宝石只能选一颗大一颗小……
int r[100005];
int g[100005];
int b[100005];
ll ans;
void Input(int *a, int n) {
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i]);
sort(a + 1, a + 1 + n);
return;
}
void Solve(int *l, int nl, int *m, int nm, int *r, int nr) {
int pl = 1, pm = 1, pr = 1;
while(pm <= nm) {
while(pl + 1 <= nl && l[pl + 1] <= m[pm])
++pl;
while(pr <= nr && r[pr] < m[pm])
++pr;
if(pr > nr)
return;
ll x = l[pl], y = m[pm], z = r[pr];
ll tmp = (x - y) * (x - y) + (y - z) * (y - z) + (x - z) * (x - z);
ans = min(ans, tmp);
++pm;
}
return;
}
void TestCase() {
int nr, ng, nb;
scanf("%d%d%d", &nr, &ng, &nb);
Input(r, nr);
Input(g, ng);
Input(b, nb);
ans = LINF;
Solve(r, nr, g, ng, b, nb);
Solve(r, nr, b, nb, g, ng);
Solve(g, ng, r, nr, b, nb);
Solve(g, ng, b, nb, r, nr);
Solve(b, nb, r, nr, g, ng);
Solve(b, nb, g, ng, r, nr);
printf("%lld\n", ans);
return;
}
所以这为什么是D题?
*E - Kaavi and Magic Spell
题意:给一个字符串 \(S\) 和一个空字符串 \(T\) ,以及一段咒文 \(P\) ,每次操作选择把 \(S\) 的第一个字符移动到 \(T\) 的前面或者后面,求有多少种方法使得 \(T\) 拥有前缀 \(P\) 。
吐槽:我连怎么验证答案存在都不会。好难哦,看题解。
题解:对于不断两边拓展的问题需要想到区间DP。
设 \(dp[l][r]\) 为长度为 \(len=r-l+1\) 的 \(S\) 的前缀匹配了 \(P\) 的 \([l,r]\) 区间的方案数,则:
\(dp[l][r]=\sum\limits_{m=l}^{r-1}dp[l][m]\)