Codeforces Round 1044 (Div. 2) (E, F)
https://codeforces.com/contest/2133
E
交互题感觉只要看给出的询问次数就能推测出做法。
显然至少每个点都要进行一次操作1,最多也就少问一个点可以忽略不计,所以剩下的次数就是用来进行操作2的。也就是说每四个点要进行操作2。手玩小样例,菊花图,二叉树,链,可以发现只要把siz大于4的模块直接截断,最后剩下的连通块大小都不超过3,也就是都是一条链,一条链的情况是直接询问得出的。(题解写法有点类似树链剖分,不过本题思维难度不高,主要在于实现难度,每四个点截断非常好写)
采用给树染色的方法,能很容易分类讨论一个连通块的三种情况(截断点,链端点为lca或者链端点不为lca)。又因为一个点有效儿子不超过2个,记录一下就很好写了。
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) (x & (-x))
#define ls(x) (x << 1)
#define int long long
#define endl '\n'
#define rs(x) (x << 1 | 1)
const int N = 2e5 + 7, MOD = 998244353;
int mul(int x, int y) {return 1ll * x * y % MOD;}
int qpow(int x, int y) {
int res = 1; while(y) {
if (y & 1) res = mul(res, x);
x = mul(x, x); y >>= 1;} return res;
}
vector<int> E[N];
vector<pair<int, int>> ans;
int n, col[N], son1[N], son2[N];
void init() {
ans.clear();
for (int i = 1; i <= n; i++)
son1[i] = son2[i] = col[i] = 0, E[i].clear();
}
void dfs(int x, int fa) {
int cnt = 0;
for (int v : E[x]) {
if (v == fa) continue;
dfs(v, x);
if (col[v] == 1) {
cnt++;
if (!son1[x]) son1[x] = v;
else son2[x] = v;
}
else if (col[v] == 2) cnt += 10;
}
if (cnt > 2) col[x] = 3;
else if (cnt == 2) col[x] = 2;
else col[x] = 1;
// cout << x << ' ' << col[x] << " ???" << endl;
}
void dfs0(int x, int fa) {
if (son1[x]) dfs0(son1[x], x);
ans.push_back({1, x});
col[x] = 3;
}
void dfs3(int x, int fa) {
int p = 0;
if (col[x] == 1) {
ans.push_back({1, x});
if (son1[x]) dfs3(son1[x], x), p = son1[x];
}
for (int i : E[x]) {
if (i == p || i == fa) continue;
dfs3(i, x);
}
}
void solve() {
cin >> n;
init();
for (int i = 1; i < n; i++) {
int u, v; cin >> u >> v;
E[u].push_back(v); E[v].push_back(u);
}
dfs(1, 0);
for (int i = 1; i <= n; i++) {
if (col[i] == 3) ans.push_back({1, i}), ans.push_back({2, i});
}
for (int i = 1; i <= n; i++) {
if (col[i] == 2) {
dfs0(son1[i], i);
ans.push_back({1, i});
int cur = son2[i];
while(cur) {
col[cur] = 3;
ans.push_back({1, cur});
cur = son1[cur];
}
}
}
dfs3(1, 0);
cout << ans.size() << endl;
for (auto i : ans) {
cout << i.first << ' ' << i.second << endl;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
int T;
cin >> T;
while(T--) solve();
}
F
线段树优化DP

浙公网安备 33010602011771号