This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#define endl '\n'
using namespace std;
const int maxn = 70003;
const int maxlog = 20;
const int inf = 1e9 + 3;
struct chain
{
int a, b, w;
chain() {}
chain(int a, int b, int w)
{
this->a = a;
this->b = b;
this->w = w;
}
bool operator < (const chain &other) const
{
return w < other.w;
}
};
int n, k;
vector <int> adj[maxn];
vector <chain> vmin, vmax;
void read()
{
cin >> n;
for (int i = 1; i <= n-1; i++)
{
int a, b;
cin >> a >> b;
adj[a].push_back(b);
adj[b].push_back(a);
}
cin >> k;
for (int i = 1; i <= k; i++)
{
char type;
int a, b, w;
cin >> type >> a >> b >> w;
if (type == 'm')
vmin.push_back(chain(a, b, w));
else
vmax.push_back(chain(a, b, w));
}
}
int sz[maxn];
int par[maxn][maxlog];
void pre_dfs(int ver)
{
sz[ver] = 1;
for (auto i: adj[ver])
if (i != par[ver][0])
{
par[i][0] = ver;
pre_dfs(i);
sz[ver] += sz[i];
}
}
int pos[maxn], head[maxn];
vector <int> order;
void dfs(int ver, int curr_head)
{
order.push_back(ver);
pos[ver] = (int)order.size()-1;
head[ver] = curr_head;
int max_sz = -1, idx = -1;
for (auto i: adj[ver])
if (i != par[ver][0])
if (sz[i] > max_sz)
max_sz = sz[i], idx = i;
if (idx != -1)
dfs(idx, curr_head);
for (auto i: adj[ver])
if (i != par[ver][0] && i != idx)
dfs(i, i);
}
void precompute()
{
pre_dfs(1);
dfs(1, 1);
for (int j = 1; j < maxlog; j++)
for (int i = 1; i <= n; i++)
par[i][j] = par[par[i][j-1]][j-1];
}
bool is_upper(int a, int b)
{
return pos[a] <= pos[b] && pos[a] + sz[a] - 1 >= pos[b];
}
int lca(int a, int b)
{
if (is_upper(a, b))
return a;
for (int i = maxlog-1; i >= 0; i--)
if (par[a][i] && !is_upper(par[a][i], b))
a = par[a][i];
return par[a][0];
}
struct node
{
int min_val, max_val;
node() {min_val = inf, max_val = -1;}
};
node tr[maxn * 4];
void update(int v, int l, int r, int ll, int rr, int val, bool type)
{
if (l > rr || r < ll)
return;
if (l >= ll && r <= rr)
{
if (type)
tr[v].min_val = min(tr[v].min_val, val);
else
tr[v].max_val = max(tr[v].max_val, val);
return;
}
int mid = (l + r) / 2;
update(v * 2, l, mid, ll, rr, val, type);
update(v * 2 + 1, mid + 1, r, ll, rr, val, type);
}
int get_min(int v, int l, int r, int pos)
{
if (l == r)
return tr[v].min_val;
int mid = (l + r) / 2;
if (pos <= mid)
return min(tr[v].min_val, get_min(v * 2, l, mid, pos));
else
return min(tr[v].min_val, get_min(v * 2 + 1, mid + 1, r, pos));
}
int get_max(int v, int l, int r, int pos)
{
if (l == r)
return tr[v].max_val;
int mid = (l + r) / 2;
if (pos <= mid)
return max(tr[v].max_val, get_max(v * 2, l, mid, pos));
else
return max(tr[v].max_val, get_max(v * 2 + 1, mid + 1, r, pos));
}
void update_min(int a, int b, int w)
{
if (a == b)
return;
while (!is_upper(head[a], b))
{
update(1, 0, n-1, pos[head[a]], pos[a], w, true);
a = par[head[a]][0];
}
update(1, 0, n-1, pos[b]+1, pos[a], w, true);
}
void update_max(int a, int b, int w)
{
if (a == b)
return;
while (!is_upper(head[a], b))
{
update(1, 0, n-1, pos[head[a]], pos[a], w, false);
a = par[head[a]][0];
}
update(1, 0, n-1, pos[b]+1, pos[a], w, false);
}
int l[maxn], r[maxn];
vector <int> adj1[maxn];
int match[maxn];
int used[maxn];
int curr_time;
bool kuhn(int ver)
{
for (auto i: adj1[ver])
if (used[i] != curr_time)
{
used[i] = curr_time;
if (match[i] == -1 || kuhn(match[i]))
{
match[i] = ver;
return true;
}
}
return false;
}
int ans[maxn];
void solve()
{
precompute();
sort (vmin.begin(), vmin.end());
sort (vmax.begin(), vmax.end());
for (auto i: vmin)
{
int curr_lca = lca(i.a, i.b);
update_max(i.a, curr_lca, i.w);
update_max(i.b, curr_lca, i.w);
}
for (auto i: vmax)
{
int curr_lca = lca(i.a, i.b);
update_min(i.a, curr_lca, i.w);
update_min(i.b, curr_lca, i.w);
}
for (int i = 2; i <= n; i++)
{
l[i] = get_max(1, 0, n-1, pos[i]);
r[i] = get_min(1, 0, n-1, pos[i]);
}
for (int i = 2; i <= n; i++)
{
int idx1 = lower_bound(vmin.begin(), vmin.end(), chain(0, 0, l[i])) - vmin.begin();
int idx2 = lower_bound(vmax.begin(), vmax.end(), chain(0, 0, r[i])) - vmax.begin();
if (l[i] != -1)
adj1[i].push_back(idx1 + 1);
if (r[i] != inf)
adj1[i].push_back(idx2 + (int)vmin.size() + 1);
}
memset(match, -1, sizeof(match));
memset(used, -1, sizeof(match));
for (int i = 2; i <= n; i++)
{
curr_time++;
kuhn(i);
}
memset(ans, -1, sizeof(ans));
for (int i = 1; i <= k; i++)
{
if (i <= (int)vmin.size())
ans[match[i]] = vmin[i-1].w;
else
ans[match[i]] = vmax[i-(int)vmin.size()-1].w;
}
for (int i = 2; i <= n; i++)
if (ans[i] == -1)
ans[i] = l[i];
for (int i = 2; i <= n; i++)
cout << i << " " << par[i][0] << " " << ans[i] << endl;
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
read();
solve();
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |