• hdu 4010 Query on the trees LCT


    维护一个带点权的无向图森林,支持:

      1、删边

      2、加边

      3、增加某条链所有点的点权

      4、求某条链上点权的最大值

    大概思路:

    前两个需要更改根(即需要翻转标记)

    第三个又需要一个标记,第四个每个节点记录该splay中以该节点为根的子树的最大点权。

    收获:

      1、对于splay前的标记下传可用递归写法, 虽然慢一点,但不容易写错。

      2、access的过程中,在边转换完成后要更新节点信息。

      3、对于寻找某子树的根,可以一直向上(会途径重边和轻边)找,这样比access+splay快很多,也很好写。

      4、标记的意义是:”我想要对这个节点的子节点操作,但不是现在“,即标记只代表需要对子节点操作而不代表需要对当前节点操作,所以在加标记时,要确保当前节点已经应用了该种操作。

      1 #include <cstdio>
      2 #include <iostream>
      3 #define fprintf(...)
      4 #define maxn 300010
      5 using namespace std;
      6 
      7 struct LCT {
      8     int pnt[maxn], pre[maxn], son[maxn][2];
      9     int val[maxn], maxv[maxn], rtag[maxn], itag[maxn];
     10 
     11     void update( int nd ) {
     12         maxv[nd] = max( val[nd], max(maxv[son[nd][0]],maxv[son[nd][1]]) );
     13     }
     14     void rotate( int nd, int d ) {
     15         int p = pre[nd];
     16         int s = son[nd][!d];
     17         int ss = son[s][d];
     18 
     19         son[nd][!d] = ss;
     20         son[s][d] = nd;
     21         if( p ) son[p][ nd==son[p][1] ] = s;
     22         else pnt[s] = pnt[nd];
     23 
     24         pre[nd] = s;
     25         pre[s] = p;
     26         pre[ss] = nd;
     27 
     28         update( nd );
     29         update( s );
     30     }
     31     void pushdown( int nd ) {
     32         if( rtag[nd] ) {
     33             int &ls = son[nd][0], &rs = son[nd][1];
     34             swap( ls, rs );
     35             rtag[ls] ^= 1;
     36             rtag[rs] ^= 1;
     37             rtag[nd] = 0;
     38         } 
     39         if( itag[nd] ) {
     40             int ls = son[nd][0], rs = son[nd][1];
     41             int delta = itag[nd];
     42             itag[ls] += delta;
     43             itag[rs] += delta;
     44             if( ls ) val[ls]  += delta;
     45             if( rs ) val[rs]  += delta;
     46             if( ls ) maxv[ls] += delta;
     47             if( rs ) maxv[rs] += delta;
     48             itag[nd] = 0;
     49         }
     50     }
     51     void big_push( int nd ) {
     52         if( pre[nd] ) big_push(pre[nd]);
     53         pushdown(nd);
     54     }
     55     void splay( int nd, int top=0 ) {
     56         big_push( nd );
     57         while( pre[nd]!=top ) {
     58             int p = pre[nd];
     59             int nl = nd==son[p][0];
     60             if( pre[p]==top ) {
     61                 rotate( p, nl );
     62             } else {
     63                 int pp = pre[p];
     64                 int pl = p==son[pp][0];
     65                 if( nl==pl ) {
     66                     rotate( pp, pl );
     67                     rotate( p, nl );
     68                 } else {
     69                     rotate( p, nl );
     70                     rotate( pp, pl );
     71                 }
     72             }
     73         }
     74     }
     75     void access( int nd ) {
     76         int u = nd;
     77         int v = 0;
     78         while( u ) {
     79             splay( u );
     80             int s = son[u][1];
     81             pre[s] = 0;
     82             pnt[s] = u;
     83             pre[v] = u;
     84             son[u][1] = v;
     85             update( u );
     86             v = u;
     87             u = pnt[u];
     88         }
     89         splay(nd);
     90     }
     91     void init( int n ) {
     92         for( int i=0; i<=n; i++ )
     93             pnt[i] = pre[i] = son[i][0] = son[i][1] = val[i] 
     94                 = maxv[i] = rtag[i] = itag[i] = 0;
     95     }
     96     void makeroot( int nd ) {
     97         access(nd);
     98         rtag[nd] = true;
     99     }
    100     void link( int u, int v ) {
    101         makeroot(u);
    102         makeroot(v);
    103         pnt[u] = v;
    104     }
    105     void cut( int rt, int u ) {
    106         makeroot(rt);
    107         access(u);
    108         int ls = son[u][0];
    109         pre[ls] = 0;
    110         pnt[ls] = pnt[u];
    111         pnt[u] = 0;
    112         son[u][0] = 0;
    113     }
    114     void modify( int nd, int w ) {
    115         splay(nd);
    116         val[nd] = w;
    117         update(nd);
    118     }
    119     int findroot( int u ) {
    120         while( pre[u] ) 
    121             u = pre[u];
    122         while( pnt[u] ) {
    123             u = pnt[u];
    124             while( pre[u] ) u=pre[u];
    125         }
    126         return u;
    127     }
    128     inline bool sameroot( int u, int v ) {
    129         return findroot(u)==findroot(v);
    130     }
    131     void inc_val( int u, int v, int w ) {
    132         makeroot(u);
    133         access(v);
    134         val[v] += w;
    135         maxv[v] += w;
    136         itag[v] += w;
    137     }
    138     int qu_max( int u, int v ) {
    139         makeroot(u);
    140         access(v);
    141         return maxv[v];
    142     }
    143 };
    144 
    145 int n, q;
    146 LCT LT;
    147 
    148 int main() {
    149     while(1) {
    150         if( scanf( "%d", &n )!=1 ) return 0;
    151         LT.init(n);
    152         for( int i=1,u,v; i<n; i++ ) {
    153             scanf( "%d%d", &u, &v );
    154             LT.link(u,v);
    155         }
    156         for( int i=1,w; i<=n; i++ ) {
    157             scanf( "%d", &w );
    158             LT.modify( i, w );
    159         }
    160         scanf( "%d", &q );
    161         for( int i=1; i<=q; i++ ) {
    162             int opt, x, y, w;
    163             scanf( "%d", &opt );
    164             if( opt==1 ) {
    165                 scanf( "%d%d", &x, &y );
    166                 if( LT.sameroot(x,y) ) 
    167                     printf( "-1
    " );
    168                 else 
    169                     LT.link(x,y);
    170             } else if( opt==2 ) {
    171                 scanf( "%d%d", &x, &y );
    172                 if( x==y || !LT.sameroot(x,y) ) 
    173                     printf( "-1
    " );
    174                 else 
    175                     LT.cut( x, y );
    176             } else if( opt==3 ) {
    177                 scanf( "%d%d%d", &w, &x, &y );
    178                 if( !LT.sameroot(x,y) ) 
    179                     printf( "-1
    " );
    180                 else 
    181                     LT.inc_val( x, y, w );
    182             } else {
    183                 scanf( "%d%d", &x, &y );
    184                 if( !LT.sameroot(x,y) ) 
    185                     printf( "-1
    " );
    186                 else 
    187                     printf( "%d
    ", LT.qu_max( x, y ) );
    188             }
    189         }
    190         printf( "
    " );
    191     }
    192 }
    View Code
  • 相关阅读:
    奥多朗WIFI 插座
    USB2.0的最高传输速率
    Win10各个版本免费激活密钥
    LINUX API函数大全
    COLLECTL LINUX 监控
    打印机工作原理
    深入理解windows系统内的GMT和时区
    searchIndexer.exe占用过高CPU
    systemtap 作用-- SystemTap使用技巧
    ADSL和ITV
  • 原文地址:https://www.cnblogs.com/idy002/p/4290982.html
Copyright © 2020-2023  润新知