[树套树] 网络管理
生活随笔
收集整理的這篇文章主要介紹了
[树套树] 网络管理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
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; }總結
以上是生活随笔為你收集整理的[树套树] 网络管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何快速选股如何利用电脑选股
- 下一篇: [LCT动态树] [NOI2014]魔法