A:[CTSC2008]网络管理
此题本来是平衡树板块的,但俺写的是树套树,平衡树会多个log
题目
查询第kkk大,天然主席树可以维护
就不用了平衡树二分,多个logloglog了
将树上(u,v)(u,v)(u,v)的路径转化为 uuu到根 +++ vvv到根 −-− lcalcalca到根 −-− lcalcalca父亲到根 四个部分
主席树维护每个点到根的所有路由器
每次修改单个路由器 则会影响该路由器的整个子树
整个子树问题转化为树上的dfndfndfn序
变成连续的一段区间
用树状数组维护四个部分的前缀和
所以这道题就是树状数组套主席树
#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;
}