Files
contests/2023/rcpc/d2/editorial/f-suceava-663.cpp
2024-04-22 16:45:09 +03:00

309 lines
7.6 KiB
C++

#include <bits/stdc++.h>
using namespace std;
ofstream out("f.out");
const int MOMMAX = 5e5;
struct edge
{
int ti,tf,x,y;
};
int n,m,t,q;
vector<int>g[100005];
map<pair<int,int>,int>color;
map<pair<int,int>,int>beg;
vector<edge>v[100005];
vector<pair<int,int>>qs[100005];///timp,index
vector<pair<int,int>>aint[4 * MOMMAX + 5];
vector<pair<int,int>>input_edges;
vector<int>inds[4 * MOMMAX + 5];
int ans[100005];
int diammax[4 * MOMMAX + 5];
int tata[100005],sz[100005],diam[100005];
pair<int,int>bestdiam[100005];
vector<int> rmq[19];
int tin[100005], depth[100005];
void _dfs(int u = 1, int v = 0) {
tin[u] = rmq[0].size();
rmq[0].emplace_back(u);
for(const auto &it: g[u]) if(it != v) {
depth[it] = depth[u] + 1;
_dfs(it, u);
rmq[0].emplace_back(u);
}
}
int _min(int u, int v) {
if(depth[u] < depth[v]) {
return u;
}
return v;
}
void init() {
_dfs();
int n = rmq[0].size();
for(int i = 1; (1 << i) <= n; i++) {
for(int j = 0; j + (1 << i) - 1 < n; j++) {
rmq[i].emplace_back(_min(rmq[i - 1][j], rmq[i - 1][j + (1 << (i - 1))]));
}
}
}
int query(int l, int r) {
int lg = __lg(r - l + 1);
return _min(rmq[lg][l], rmq[lg][r - (1 << lg) + 1]);
}
int lca(int u, int v) {
int l = tin[u], r = tin[v];
if(l > r) {
swap(l, r);
}
return query(l, r);
}
int dist(int u, int v) {
return depth[u] + depth[v] - 2 * depth[lca(u, v)];
}
void update(int nod,int l,int r,int st,int dr,pair<int,int>p)
{
if (r < st or dr < l)
return;
if (st <= l and r <= dr)
{
aint[nod].push_back(p);
return;
}
int mij = (l + r) / 2;
update(2 * nod,l,mij,st,dr,p);
update(2 * nod + 1,mij + 1,r,st,dr,p);
}
void setquery(int nod,int l,int r,int pos,int index)
{
if (l == r)
inds[nod].push_back(index);
else
{
int mij = (l + r) / 2;
if (pos <= mij)
setquery(2 * nod,l,mij,pos,index);
else
setquery(2 * nod + 1,mij + 1,r,pos,index);
}
}
struct stack_upd
{
int x,y,antx;
pair<int,int>antbestx;
///x a devenit tatal lui y
///x avea diam antx
///size-ul anterior al lui y o sa ramana in sz[y]
///diametrul anterior al lui y o sa ramane in diam[y]
};
stack<stack_upd>stk;
int reprez(int x)
{
while (x != tata[x])
x = tata[x];
return x;
}
void baga(int nod,int x,int y)
{
//cout << "super" << endl;
x = reprez(x);
y = reprez(y);
if (sz[x] < sz[y])
swap(x,y);
stack_upd aux;
aux.x = x;
aux.y = y;
aux.antbestx = bestdiam[x];
aux.antx = diam[x];
stk.push(aux);
tata[aux.y] = aux.x;
int maxim = max(diam[x],diam[y]);
maxim = max(maxim,dist(bestdiam[x].first,bestdiam[y].first));
maxim = max(maxim,dist(bestdiam[x].first,bestdiam[y].second));
maxim = max(maxim,dist(bestdiam[x].second,bestdiam[y].first));
maxim = max(maxim,dist(bestdiam[x].second,bestdiam[y].second));
//cout << x << ' ' << y << ' ' << diam[x] << ' ' << diam[y] << ' ' << dist(bestdiam[x].first,bestdiam[y].first) << ' ' << dist(bestdiam[x].first,bestdiam[y].second) << ' ' << dist(bestdiam[x].second,bestdiam[y].first) << ' ' << dist(bestdiam[x].second,bestdiam[y].second) << endl;
diammax[nod] = max(diammax[nod],maxim);
if (diam[x] == maxim)
{
return;
}
if (diam[y] == maxim)
{
diam[x] = diam[y];
bestdiam[x] = bestdiam[y];
return;
}
if (dist(bestdiam[x].first,bestdiam[y].first) == maxim)
{
diam[x] = dist(bestdiam[x].first,bestdiam[y].first);
bestdiam[x] = {bestdiam[x].first,bestdiam[y].first};
return;
}
if (dist(bestdiam[x].first,bestdiam[y].second) == maxim)
{
diam[x] = dist(bestdiam[x].first,bestdiam[y].second);
bestdiam[x] = {bestdiam[x].first,bestdiam[y].second};
return;
}
if (dist(bestdiam[x].second,bestdiam[y].first) == maxim)
{
diam[x] = dist(bestdiam[x].second,bestdiam[y].first);
bestdiam[x] = {bestdiam[x].second,bestdiam[y].first};
return;
}
if (dist(bestdiam[x].second,bestdiam[y].second) == maxim)
{
diam[x] = dist(bestdiam[x].second,bestdiam[y].second);
bestdiam[x] = {bestdiam[x].second,bestdiam[y].second};
return;
}
}
void rollback()
{
stack_upd aux = stk.top();
stk.pop();
tata[aux.y] = aux.y;
sz[aux.x] -= sz[aux.y];
diam[aux.x] = aux.antx;
bestdiam[aux.x] = aux.antbestx;
}
void dfs(int nod,int l,int r)
{
/*if (!aint[nod].empty())
{
cout << nod << ' ' << l << ' ' << r << endl;
for (auto it : aint[nod])
cout << it.first << ' ' << it.second << endl;
cout << endl;
}*/
diammax[nod] = diammax[nod / 2];
for (auto it : aint[nod])
baga(nod,it.first,it.second);
//if (!aint[nod].empty() or !inds[nod].empty())
// cout << nod << ' ' << l << ' ' << r << ' ' << diammax[nod] << '\n';
if (l == r)
{
for (auto it : inds[nod])
ans[it] = diammax[nod];
}
else
{
int mij = (l + r) / 2;
dfs(2 * nod,l,mij);
dfs(2 * nod + 1,mij + 1,r);
}
for (int i = 0; i < aint[nod].size(); i++)
rollback();
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> n >> m;
for (int i = 1; i < n; i++)
{
int x,y,cc;
cin >> x >> y >> cc;
if (x > y)
swap(x,y);
color[{x,y}] = cc;
g[x].push_back(y);
g[y].push_back(x);
beg[{x,y}] = 1;
input_edges.push_back({x,y});
}
for (int i = 1; i <= n; i++)
tata[i] = i,sz[i] = 1,diam[i] = 0,bestdiam[i] = {i,i};
init();
cin >> t;
for (int i = 1; i <= t; i++)
{
int x,y,cc;
cin >> x >> y >> cc;
if (x > y)
swap(x,y);
edge aux;
aux.x = x;
aux.y = y;
aux.ti = beg[{x,y}];
aux.tf = i;
v[color[{x,y}]].push_back(aux);
color[{x,y}] = cc;
beg[{x,y}] = i + 1;
}
for (int i = 0; i < n - 1; i++)
{
int x = input_edges[i].first,y = input_edges[i].second;
edge aux;
aux.x = x;
aux.y = y;
aux.tf = t + 1;
aux.ti = beg[{x,y}];
v[color[{x,y}]].push_back(aux);
}
cin >> q;
for (int i = 1; i <= q; i++)
{
int cc,tmp;
cin >> cc >> tmp;
tmp++;
qs[cc].push_back({tmp,i});
}
int ft = 0;
for (int i = 1; i <= m; i++)
{
//cout << i << endl;
vector<int>vals;
for (auto it : v[i])
vals.push_back(it.ti),vals.push_back(it.tf);
for (auto it : qs[i])
vals.push_back(it.first);
sort(vals.begin(),vals.end());
if (vals.size() == 0)
continue;
map<int,int>mpnorma;
int posnorma = 0;
for (auto it : vals)
if (!mpnorma[it])
mpnorma[it] = ++posnorma;
for (int j = 0; j < v[i].size(); j++)
v[i][j].ti = mpnorma[v[i][j].ti] + ft,v[i][j].tf = mpnorma[v[i][j].tf] + ft;
for (int j = 0; j < qs[i].size(); j++)
qs[i][j].first = mpnorma[qs[i][j].first] + ft;
//for (auto it : v[i])
// cout << it.ti << ' ' << it.tf << ' ' << it.x << ' ' << it.y << endl;
//for (auto it : qs[i])
// cout << it.first << ' ' << it.second << endl;
for (int j = 0; j < v[i].size(); j++)
update(1,1,MOMMAX,v[i][j].ti,v[i][j].tf,{v[i][j].x,v[i][j].y});
for (int j = 0; j < qs[i].size(); j++)
setquery(1,1,MOMMAX,qs[i][j].first,qs[i][j].second);
ft += posnorma;
}
dfs(1,1,MOMMAX);
for (int i = 1; i <= q; i++)
cout << ans[i] << '\n';
return 0;
}