A:[CTSC2008]网络管理
此题本来是平衡树板块的,但俺写的是树套树,平衡树会多个log
题目
查询第 k k k大,天然主席树可以维护
就不用了平衡树二分,多个 l o g log log了
将树上 ( u , v ) (u,v) (u,v)的路径转化为 u u u到根 + + + v v v到根 − - − l c a lca lca到根 − - − l c a lca lca父亲到根 四个部分
主席树维护每个点到根的所有路由器
每次修改单个路由器 则会影响该路由器的整个子树
整个子树问题转化为树上的 d f n dfn dfn序
变成连续的一段区间
用树状数组维护四个部分的前缀和
所以这道题就是树状数组套主席树
#include <cstdio>
#include <vector>
#include <iostream>
using namespace std;
#define maxn 80005
#define MAX 1e8
vector < int > G[maxn];
int n, Q, num;
int ti[maxn], dep[maxn], Start[maxn], End[maxn];
int sum[maxn * 300], lson[maxn * 300], rson[maxn * 300], root[maxn];//log^2±¶
int f[maxn][20];
int lowbit( int x ) {
return x & ( -x );
}
struct node {
int cnt, t[maxn];
int calc() {
int tot = 0;
for( int i = 1;i <= cnt;i ++ ) tot += sum[rson[t[i]]];
return tot;
}
void init( int x ) {
cnt = 0;
while( x ) t[++ cnt] = root[x], x -= lowbit( x );
}
void choose_l() {
for( int i = 1;i <= cnt;i ++ ) t[i] = lson[t[i]];
}
void choose_r() {
for( int i = 1;i <= cnt;i ++ ) t[i] = rson[t[i]];
}
}t1, t2, t3, t4;
void dfs( int u, int fa ) {
dep[u] = dep[fa] + 1, f[u][0] = fa, Start[u] = ++ num;
for( int i = 1;i < 18;i ++ )
f[u][i] = f[f[u][i - 1]][i - 1];
for( int i = 0;i < G[u].size();i ++ ) {
int v = G[u][i];
if( v == fa ) continue;
else dfs( v, u );
}
End[u] = num;
}
int LCA( int u, int v ) {
if( dep[u] < dep[v] ) swap( u, v );
for( int i = 17;~ i;i -- )
if( dep[f[u][i]] >= dep[v] )
u = f[u][i];
if( u == v ) return u;
for( int i = 17;~ i;i -- )
if( f[u][i] != f[v][i] )
u = f[u][i], v = f[v][i];
return f[u][0];
}
void modify( int &x, int l, int r, int pos, int v ) {
if( ! x ) x = ++ num;
sum[x] += v;
if( l == r ) return;
int mid = ( l + r ) >> 1;
if( pos <= mid ) modify( lson[x], l, mid, pos, v );
else modify( rson[x], mid + 1, r, pos, v );
}
void modify( int x, int pos, int c ) {
while( x <= n ) {
modify( root[x], 1, MAX, pos, c );
x += lowbit( x );
}
}
int query( int l, int r, int k ) {
if( l == r ) return l;
int mid = ( l + r ) >> 1;
int tot = t1.calc() + t2.calc() - t3.calc() - t4.calc();
if( tot >= k ) {
t1.choose_r(), t2.choose_r(), t3.choose_r(), t4.choose_r();
return query( mid + 1, r, k );
}
else {
t1.choose_l(), t2.choose_l(), t3.choose_l(), t4.choose_l();
return query( l, mid, k - tot );
}
}
int main() {
scanf( "%d %d", &n, &Q );
for( int i = 1;i <= n;i ++ )
scanf( "%d", &ti[i] );
for( int i = 1, u, v;i < n;i ++ ) {
scanf( "%d %d", &u, &v );
G[u].push_back( v );
G[v].push_back( u );
}
dfs( 1, 0 ); num = 0;
for( int i = 1;i <= n;i ++ )
modify( Start[i], ti[i], 1 ), modify( End[i] + 1, ti[i], -1 );
for( int i = 1, k, x, y;i <= Q;i ++ ) {
scanf( "%d %d %d", &k, &x, &y );
if( k ) {
int lca = LCA( x, y );
if( dep[x] + dep[y] - ( dep[lca] << 1 ) + 1 < k ) {
printf( "invalid request!\n" );
continue;
}
t1.init( Start[x] ), t2.init( Start[y] ), t3.init( Start[lca] ), t4.init( Start[f[lca][0]] );
printf( "%d\n", query( 1, MAX, k ) );
}
else {
modify( Start[x], ti[x], -1 ), modify( End[x] + 1, ti[x], 1 );
ti[x] = y;
modify( Start[x], ti[x], 1 ), modify( End[x] + 1, ti[x], -1 );
}
}
return 0;
}