• 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
    ", 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
  • 相关阅读:
    区块链系列教程
    第三章 通过java SDK 实现个性化智能合约的部署与测试
    第一章 区块链系列 联盟链FISCO BCOS 底层搭建
    ABP 框架 数据库底层迁移 Mysql 集群
    ABP 框架代码批量生成器
    基于百度理解与交互技术实现机器问答
    微软人工智能和对话平台--知识商城体验
    基于百度AI实现 车牌识别
    最近整理AI相关感想
    百度OCR文字识别-身份证识别
  • 原文地址:https://www.cnblogs.com/idy002/p/4290875.html
Copyright © 2020-2023  润新知