spoj 375 query on a tree LCT

 

这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的)。

收获:

  1、边转换成点(即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一)。

  2、若要连接两个点u,v,先让它们分别称为根,然后将其中一个的path-parent设为另一个。

  3、若要查找(u,v)的边点,运用“夹逼法”,先让两个点在一条重链上(即同一棵splay树),再splay(u,0)和splay(v,u),这样v的一个子树就是边点(具体来说,可以先让u成为根,再access(v),splay(u,0),splay(v,u),此时v的左儿子必定是边点)

 

  1 #include <cstdio>
  2 #include <iostream>
  3 #define maxn 20010
  4 #define oo 0x3f3f3f3f
  5 #define max(a,b) ((a)>(b)?(a):(b))
  6 using namespace std;
  7 
  8 struct LCT {
  9     int pnt[maxn], pre[maxn], son[maxn][2], val[maxn], mxv[maxn], ntot;
 10     bool tag[maxn];
 11 
 12     inline void update( int nd ) {
 13         mxv[nd] = max( val[nd], max( mxv[son[nd][0]], mxv[son[nd][1]] ) );
 14     }
 15     void rotate( int nd, int d ) {
 16         int p = pre[nd];
 17         int s = son[nd][!d];
 18         int ss = son[s][d];
 19 
 20         son[nd][!d] = ss;
 21         son[s][d] = nd;
 22         if( p ) son[p][ nd==son[p][1] ] = s;
 23         else pnt[s] = pnt[nd];
 24 
 25         pre[nd] = s;
 26         pre[s] = p;
 27         if( ss ) pre[ss] = nd;
 28 
 29         update( nd );
 30         update( s );
 31     }
 32     inline void pushdown( int nd ) {
 33         if( tag[nd] ) {
 34             int &ls = son[nd][0], &rs = son[nd][1];
 35             swap( ls, rs );
 36             tag[ls] ^= 1;
 37             tag[rs] ^= 1;
 38             tag[nd] = 0;
 39         }
 40     }
 41     void splay( int nd, int top=0 ) {
 42         static int stk[maxn], spt;
 43         int u = nd;
 44         for( spt=0; u; u=pre[u] )
 45             stk[spt++] = u;
 46         while( spt-- )
 47             pushdown( stk[spt] );
 48         while( pre[nd]!=top ) {
 49             int p = pre[nd];
 50             int nl = nd==son[p][0];
 51             if( pre[p]==top ) {
 52                 rotate( p, nl );
 53             } else {
 54                 int pp = pre[p];
 55                 int pl = p==son[pp][0];
 56                 if( nl==pl ) {
 57                     rotate( pp, pl );
 58                     rotate( p, nl );
 59                 } else {
 60                     rotate( p, nl );
 61                     rotate( pp, pl );
 62                 }
 63             }
 64         }
 65     }
 66      void init( int n ) {
 67         for( int i=0; i<=n; i++ ) {
 68             pre[i] = pnt[i] = son[i][0] = son[i][1] = tag[i] = 0;
 69             mxv[i] = val[i] = -oo;
 70         }
 71     }
 72     void access( int nd ) {
 73         int u = nd;
 74         int v = 0;
 75         while( u ) {
 76             splay( u );
 77             int s = son[u][1];
 78             pre[s] = 0;
 79             pnt[s] = u;
 80             pre[v] = u;
 81             son[u][1] = v;
 82             v = u;
 83             u = pnt[u];
 84         }
 85         splay( nd );
 86     }
 87     void makeroot( int nd ) {
 88         access( nd );
 89         tag[nd] ^= 1;
 90     }
 91     void link( int u, int v ) {
 92         makeroot(u);
 93         makeroot(v);
 94         pnt[u] = v;
 95     }
 96     void modify( int e, int w ) {
 97         splay(e);
 98         val[e] = w;
 99         update( e );
100     }
101     int query( int u, int v ) {
102         makeroot(u);
103         access(v);
104         return max(val[v],mxv[son[v][0]]);
105     }
106 };
107 
108 int n;
109 LCT LT;
110 
111 int main() {
112     int T;
113     scanf( "%d", &T );
114     while( T-- ) {
115         scanf( "%d", &n );
116         LT.init(n+n-1);
117         for( int i=1,u,v,w; i<n; i++ ) {
118             scanf( "%d%d%d", &u, &v, &w );
119             LT.modify( n+i, w );
120             LT.link( u, n+i );
121             LT.link( v, n+i );
122         }
123         while(1) {
124             char ch[10];
125             scanf( "%s", ch );
126             if( ch[0]=='Q' ) {
127                 int u, v;
128                 scanf( "%d%d", &u, &v );
129                 printf( "%d\n", LT.query(u,v) );
130             } else if( ch[0]=='C' ) {
131                 int e, w;
132                 scanf( "%d%d", &e, &w );
133                 LT.modify( n+e, w );
134             } else break;
135         }
136     }
137 }
View Code

 

posted @ 2015-02-13 20:29  idy002  阅读(179)  评论(0编辑  收藏  举报