Problem Link : Tree operations
Category : Approximate Problem
Contest : December Circuits'23
#include "bits/stdc++.h"
using namespace std;
#define int long long int
#define endl '\n'
using pii = pair<int, int>;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
int Rand(int l, int r) {
int rnd = uniform_int_distribution<int>(l, r)(rng);
return rnd;
}
const int maxn = 2e5 + 5;
const int logn = 20;
int n;
int k;
int arr[maxn];
vector<vector<int>> graph;
int depth[maxn];
int father[maxn][logn];
void dfs(int u, int p, int lvl) {
depth[u] = lvl;
for (int i = 1; i < logn; i++) {
father[u][i] = father[ father[u][i - 1] ][i - 1];
}
for (int v : graph[u]) {
if (v == p) {
continue;
}
father[v][0] = u;
dfs(v, u, lvl + 1);
}
}
int findLca(int u, int v) {
if (depth[u] < depth[v]) {
swap(u, v);
}
for (int i = logn - 1; i >= 0; i--) {
if (depth[ father[u][i] ] >= depth[v]) {
u = father[u][i];
}
}
if (u == v) {
return u;
}
for (int i = logn - 1; i >= 0; i--) {
if (father[u][i] != father[v][i]) {
u = father[u][i];
v = father[v][i];
}
}
return father[u][0];
}
vector<int> up(int u, int lca, bool isForV = false) {
vector<int> curPath;
do {
curPath.emplace_back(u);
if (u == lca) {
break;
}
u = father[u][0];
} while (true);
if (isForV) {
reverse(curPath.begin(), curPath.end());
curPath.pop_back();
}
return curPath;
}
int getEdgesSum(int u, int p) {
int sum = 0;
for (int v : graph[u]) {
if (v == p) {
continue;
}
int add = (arr[u] ^ arr[v]) * (arr[u] | arr[v]);
sum += add + getEdgesSum(v, u);
}
return sum;
}
int solve(int &u, int &v, int operations) {
u = Rand(1, n);
v = Rand(1, n);
int lca = findLca(u, v);
vector<int> pathOfU = up(u, lca);
vector<int> pathOfV = up(v, lca, true);
vector<int> path;
for (int x : pathOfU) {
path.push_back(x);
}
for (int x : pathOfV) {
path.push_back(x);
}
int sz = path.size();
int temp = arr[ path[0] ];
for (int i = 0; i < path.size(); i++) {
int j = (i + 1) % sz;
arr[ path[i] ] = j == 0 ? temp : arr[ path[j] ];
}
int sum = getEdgesSum(1, 0);
return sum * (k - operations + 1);
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout.precision(12);
bool FILEIO = 1;
if (FILEIO and fopen("in.txt", "r")) {
freopen("in.txt", "r", stdin);
}
cin >> n >> k;
graph.resize(n + 1);
for (int i = 1; i <= n; i++) {
cin >> arr[i];
}
for (int e = 1; e < n; e++) {
int u, v;
cin >> u >> v;
graph[u].push_back(v);
graph[v].push_back(u);
}
dfs(1, 0, 1);
int maxi = 0;
int optimalOperation = 0;
vector<pii> choosenNodes;
for (int operations = 1; operations <= k; operations++) {
int u;
int v;
int curSum = solve(u, v, operations);
choosenNodes.push_back(pii(u, v));
if (curSum > maxi) {
optimalOperation = operations;
maxi = curSum;
}
}
cout << optimalOperation << endl;
for (int i = 0; i < optimalOperation; i++) {
cout << choosenNodes[i].first << " " << choosenNodes[i].second << endl;
}
}
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.