#include <bits/stdc++.h>
using namespace std;
struct query {
int u, v, w;
bool operator < ( const query &q ) const {
return w < q.w;
}
};
const int INF = (1 << 30);
const int MAX_N = 7e4 + 1;
const int MAX_LOG_N = 16;
const int undef = -1;
bool used[MAX_N];
int depth[MAX_N], parent[MAX_LOG_N + 1][MAX_N], asc[MAX_N], queryMin[MAX_N], queryMax[MAX_N], value[MAX_N];
vector<int> edges[MAX_N];
vector<query> mins, maxs;
void dfs( int u, int p ) {
depth[u] = depth[p] + 1;
parent[0][u] = p;
for ( int v: edges[u] ) {
if ( v == p )
continue;
dfs( v, u );
}
}
int lca( int u, int v ) {
if ( depth[u] > depth[v] )
swap( u, v );
for ( int p = MAX_LOG_N; p >= 0; p-- ) {
if ( depth[parent[p][v]] >= depth[u] )
v = parent[p][v];
}
if ( u == v )
return u;
for ( int p = MAX_LOG_N; p >= 0; p-- ) {
if ( parent[p][u] != parent[p][v] ) {
u = parent[p][u];
v = parent[p][v];
}
}
return parent[0][v];
}
int findParent( int u, int d ) {
for ( int p = MAX_LOG_N; p >= 0; p-- ) {
if ( d >= (1 << p) ) {
u = parent[p][u];
d -= (1 << p);
}
}
return u;
}
void init( int n ) {
for ( int p = 1; p <= MAX_LOG_N; p++ ) {
for ( int u = 1; u <= n; u++ )
parent[p][u] = parent[p - 1][parent[p - 1][u]];
}
}
struct MATCH {
const int NIL = 0;
int n, m;
int pairU[MAX_N + 1], pairV[MAX_N + 1], dist[MAX_N + 1];
vector <int> edges[MAX_N + 1];
void init( int _n, int _m ) {
n = _n;
m = _m;
}
void add_edge( int u, int v ) {
edges[u].push_back( v );
}
bool bfs() {
int u;
queue <int> q;
dist[NIL] = INF;
for ( u = 1; u <= n; u++ ) {
if ( pairU[u] == NIL ) {
dist[u] = 0;
q.push( u );
} else
dist[u] = INF;
}
while ( !q.empty() ) {
u = q.front();
q.pop();
if ( dist[u] < dist[NIL] ) {
for ( int v: edges[u] ) {
if ( dist[pairV[v]] == INF ) {
dist[pairV[v]] = dist[u] + 1;
q.push( pairV[v] );
}
}
}
}
return dist[NIL] != INF;
}
bool dfs( int u ) {
if ( u == NIL )
return true;
for ( int v: edges[u] ) {
if ( dist[pairV[v]] == dist[u] + 1 && dfs( pairV[v] ) ) {
pairU[u] = v;
pairV[v] = u;
return true;
}
}
dist[u] = INF;
return false;
}
void maxMatch() {
int maxMatch, u, v;
for ( u = 0; u <= n; u++ )
pairU[u] = NIL;
for ( v = 0; v <= m; v++ )
pairV[v] = NIL;
while ( bfs() ) {
for ( u = 1; u <= n; u++ ) {
if ( pairU[u] == NIL )
dfs( u );
}
}
}
};
MATCH match;
struct info {
int minn, maxx;
info operator + ( const info &x ) const {
return { min( minn, x.minn ), max( maxx, x.maxx ) };
}
};
struct SegTree {
info segTree[4 * MAX_N];
info lazy[4 * MAX_N];
void init() {
for ( int v = 0; v < 4 * MAX_N; v++ ) {
lazy[v] = segTree[v] = { INF, -INF };
}
}
void propag( int v, int l, int r ) {
segTree[v] = segTree[v] + lazy[v];
if ( l != r ) {
lazy[v * 2 + 1] = lazy[v * 2 + 1] + lazy[v];
lazy[v * 2 + 2] = lazy[v * 2 + 2] + lazy[v];
}
}
void update( int v, int l, int r, int lu, int ru, info x ) {
propag( v, l, r );
if ( l > ru || r < lu )
return;
if ( lu <= l && r <= ru ) {
lazy[v] = x;
propag( v, l, r );
return;
}
int mid = (l + r) / 2;
update( v * 2 + 1, l, mid, lu, ru, x );
update( v * 2 + 2, mid + 1, r, lu, ru, x );
segTree[v] = segTree[v * 2 + 1] + segTree[v * 2 + 2];
}
info query( int v, int l, int r, int lq, int rq ) {
propag( v, l, r );
if ( l > rq || r < lq )
return { INF, -INF };
if ( lq <= l && r <= rq )
return segTree[v];
int mid = (l + r) / 2;
return query( v * 2 + 1, l, mid, lq, rq ) + query( v * 2 + 2, mid + 1, r, lq, rq );
}
};
struct HPD {
int n, curPos;
int sz[MAX_N], parent[MAX_N], depth[MAX_N], heavy[MAX_N], head[MAX_N], leftPos[MAX_N];
SegTree aint;
void dfs( int u, int p ) {
int maxSz = -1;
parent[u] = p;
depth[u] = depth[p] + 1;
sz[u] = 1;
heavy[u] = undef;
for ( int v: edges[u] ) {
if ( v == p )
continue;
dfs( v, u );
sz[u] += sz[v];
if ( sz[v] > maxSz ) {
maxSz = sz[v];
heavy[u] = v;
}
}
}
void decomp( int u, int p, int h ) {
head[u] = h;
leftPos[u] = ++curPos;
if ( heavy[u] != undef )
decomp( heavy[u], u, h );
for ( int v: edges[u] ) {
if ( v == p || v == heavy[u] )
continue;
decomp( v, u, v );
}
}
void init( int _n ) {
n = _n;
aint.init();
dfs( 1, 0 );
decomp( 1, 0, 1 );
}
void updatePath( int u, int v, info x ) {
while ( head[u] != head[v] ) {
if ( depth[head[u]] < depth[head[v]] )
swap( u, v );
aint.update( 0, 1, n, leftPos[head[u]], leftPos[u], x );
u = parent[head[u]];
}
if ( depth[u] > depth[v] )
swap( u, v );
aint.update( 0, 1, n, leftPos[u], leftPos[v], x );
}
info queryVertex( int u ) {
return aint.query( 0, 1, n, leftPos[u], leftPos[u] );
}
};
HPD arb;
unordered_map<int, int> indx;
int main() {
int n, k;
cin >> n;
for ( int i = 0; i < n - 1; i++ ) {
int u, v;
cin >> u >> v;
edges[u].push_back( v );
edges[v].push_back( u );
}
dfs( 1, 0 );
init( n );
cin >> k;
for ( int i = 0; i < k; i++ ) {
char ch;
int u, v, w;
cin >> ch >> u >> v >> w;
if ( ch == 'm' )
mins.push_back( { u, v, w } );
else
maxs.push_back( { u, v, w } );
}
arb.init( n );
for ( int i = 0; i < mins.size(); i++ ) {
indx[mins[i].w] = i;
int u = mins[i].u, v = mins[i].v;
int l = lca( u, v );
arb.updatePath( mins[i].u, mins[i].v, { INF, mins[i].w } );
}
for ( int i = 0; i < maxs.size(); i++ ) {
indx[maxs[i].w] = i;
int u = maxs[i].u, v = maxs[i].v;
int l = lca( u, v );
arb.updatePath( maxs[i].u, maxs[i].v, { maxs[i].w, -INF } );
}
indx[INF] = indx[-INF] = -1;
for ( int u = 2; u <= n; u++ ) {
queryMin[u] = indx[arb.queryVertex( u ).maxx];
queryMax[u] = indx[arb.queryVertex( u ).minn];
}
match.init( k, n - 1 );
for ( int u = 2; u <= n; u++ ) {
if ( queryMin[u] != -1 )
match.add_edge( queryMin[u] + 1, u - 1 );
if ( queryMax[u] != -1 )
match.add_edge( mins.size() + queryMax[u] + 1, u - 1 );
}
match.maxMatch();
for ( int u = 2; u <= n; u++ )
value[u] = undef;
for ( int i = 0; i < mins.size(); i++ )
value[match.pairU[i + 1] + 1] = mins[i].w;
for ( int i = 0; i < maxs.size(); i++ )
value[match.pairU[mins.size() + i + 1] + 1] = maxs[i].w;
for ( int u = 2; u <= n; u++ ) {
if ( value[u] == undef ) {
if ( queryMin[u] != undef )
value[u] = mins[queryMin[u]].w;
else if ( queryMax[u] != undef )
value[u] = maxs[queryMax[u]].w;
else
value[u] = 0;
}
cout << u << " " << parent[0][u] << " " << value[u] << "\n";
}
return 0;
}
Compilation message
minmaxtree.cpp: In member function 'void MATCH::maxMatch()':
minmaxtree.cpp:131:13: warning: unused variable 'maxMatch' [-Wunused-variable]
131 | int maxMatch, u, v;
| ^~~~~~~~
minmaxtree.cpp: In function 'int main()':
minmaxtree.cpp:298:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
298 | for ( int i = 0; i < mins.size(); i++ ) {
| ~~^~~~~~~~~~~~~
minmaxtree.cpp:301:13: warning: unused variable 'l' [-Wunused-variable]
301 | int l = lca( u, v );
| ^
minmaxtree.cpp:304:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
304 | for ( int i = 0; i < maxs.size(); i++ ) {
| ~~^~~~~~~~~~~~~
minmaxtree.cpp:307:13: warning: unused variable 'l' [-Wunused-variable]
307 | int l = lca( u, v );
| ^
minmaxtree.cpp:328:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
328 | for ( int i = 0; i < mins.size(); i++ )
| ~~^~~~~~~~~~~~~
minmaxtree.cpp:330:24: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<query>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
330 | for ( int i = 0; i < maxs.size(); i++ )
| ~~^~~~~~~~~~~~~
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
7 ms |
8032 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
226 ms |
38816 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
153 ms |
23004 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Incorrect |
7 ms |
8032 KB |
Output isn't correct |
2 |
Halted |
0 ms |
0 KB |
- |