[HNOI2016]网络
problem
solution
另辟蹊径,不把交互请求赋在新增路径上,反而把交互请求赋在树上除去该请求路径覆盖点的其它点上
显然,路径问题树剖是非常可以的、
那么一个点上的信息就表示所有不经过该点的交互请求,用堆存储下来
但是又有交互请求删除问题,就在点上再来一个堆存储已经删除的请求
查询就相当于单点查询,两个大根堆,如果堆头相同,就删去,直到堆头不同
code
#include <queue>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define maxn 200005
pair < int, int > path[maxn];
int n, m, cnt;
vector < int > G[maxn];
int dfn[maxn], dep[maxn], Top[maxn], siz[maxn], son[maxn], f[maxn];
struct node {
int u, v, w;
node(){}
node( int U, int V, int W ) {
u = U, v = V, w = W;
}
}opt[maxn];
class New_Queue {
private :
priority_queue < int > Delete, Vis;
public :
int find() {
while( ! Delete.empty() && ! Vis.empty() ) {
if( Delete.top() == Vis.top() )
Delete.pop(), Vis.pop();
else
break;
}
return Vis.empty() ? -1 : Vis.top();
}
void insert( int x ) {
Vis.push( x );
}
void erase( int x ) {
Delete.push( x );
}
};
class SegMentTree {
private :
New_Queue t[maxn << 2];
public :
void modify( int num, int l, int r, int L, int R, int w, int opt ) {
if( r < L || R < l ) return;
if( L <= l && r <= R ) {
opt ? t[num].insert( w ) : t[num].erase( w );
return;
}
int mid = ( l + r ) >> 1;
modify( num << 1, l, mid, L, R, w, opt );
modify( num << 1 | 1, mid + 1, r, L, R, w, opt );
}
int query( int num, int l, int r, int pos ) {
if( l == r ) return t[num].find();
int mid = ( l + r ) >> 1;
if( pos <= mid )
return max( t[num].find(), query( num << 1, l, mid, pos ) );
else
return max( t[num].find(), query( num << 1 | 1, mid + 1, r, pos ) );
}
}MS;
void dfs1( int u, int fa ) {
f[u] = fa, dep[u] = dep[fa] + 1, siz[u] = 1;
for( int i = 0;i < G[u].size();i ++ ) {
int v = G[u][i];
if( v == fa ) continue;
else dfs1( v, u );
siz[u] += siz[v];
if( ! son[u] || siz[v] > siz[son[u]] )
son[u] = v;
}
}
void dfs2( int u, int t ) {
dfn[u] = ++ cnt, Top[u] = t;
if( ! son[u] ) return;
else dfs2( son[u], t );
for( int i = 0;i < G[u].size();i ++ ) {
int v = G[u][i];
if( v == f[u] || v == son[u] ) continue;
else dfs2( v, v );
}
}
void modify( int u, int v, int w, int opt ) {
cnt = 0;
while( Top[u] ^ Top[v] ) {
if( dep[Top[u]] < dep[Top[v]] ) swap( u, v );
path[++ cnt] = make_pair( dfn[Top[u]], dfn[u] );
u = f[Top[u]];
}
if( dep[u] < dep[v] ) swap( u, v );
path[++ cnt] = make_pair( dfn[v], dfn[u] );
sort( path + 1, path + cnt + 1 );
for( int i = 1, k = 0;i <= cnt;k = path[i ++].second )
if( k + 1 != path[i].first )
MS.modify( 1, 1, n, k + 1, path[i].first - 1, w, opt );
if( path[cnt].second ^ n )
MS.modify( 1, 1, n, path[cnt].second + 1, n, w, opt );
}
int main() {
scanf( "%d %d", &n, &m );
for( int i = 1, u, v;i < n;i ++ ) {
scanf( "%d %d", &u, &v );
G[u].push_back( v );
G[v].push_back( u );
}
dfs1( 1, 0 ), dfs2( 1, 1 );
for( int i = 1, type, a, b, v;i <= m;i ++ ) {
scanf( "%d %d", &type, &a );
switch( type ) {
case 0 : {
scanf( "%d %d", &b, &v );
opt[i] = node( a, b, v );
modify( a, b, v, 1 );
break;
}
case 1 : {
modify( opt[a].u, opt[a].v, opt[a].w, 0 );
break;
}
case 2 : {
printf( "%d\n", MS.query( 1, 1, n, dfn[a] ) );
break;
}
}
}
return 0;
}