POJ 3237 Tree 树链剖分

来源:互联网 发布:linux复制文件内容 编辑:程序博客网 时间:2024/05/16 06:58
#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;#define mxn 10020#define mxe 20020#define md ( ( ll + rr ) >> 1 )#define ls ( i << 1 )#define rs ( ls | 1 )int is[mxn];struct tree {int fst[mxn], nxt[mxe], to[mxe], cost[mxe], e, val[mxn], w[mxn];int fa[mxn], dep[mxn], sz[mxn], son[mxn];int tid[mxn], top[mxn];bool vis[mxn];int label, n;void init( int n ) {this -> n = n;memset( fst, -1, sizeof( fst ) );e = 0;}void add( int u, int v, int c ) {to[e] = v, nxt[e] = fst[u], cost[e] = c;fst[u] = e++;}void dfs( int u, int p ) {fa[u] = p;sz[u] = 1;for( int i = fst[u]; ~i; i = nxt[i] ) {int v = to[i], c = cost[i];if( v == p )continue;dep[v] = dep[u] + 1;is[i>>1] = v;val[v] = c;dfs( v, u );sz[u] += sz[v];if( sz[v] > sz[son[u]] )son[u] = v;}}void dfs2( int u, int t ) {vis[u] = 1;top[u] = t;tid[u] = ++label;w[label] = val[u];if( son[u] )dfs2( son[u], t );for( int i = fst[u]; ~i; i = nxt[i] ) {int v = to[i];if( !vis[v] )dfs2( v, v );}}void cut() {dep[1] = sz[0] = 0;memset( son, 0, sizeof( son ) );dfs( 1, -1 );memset( vis, 0, sizeof( vis ) );label = 0;dfs2( 1, 1 );}int mx[mxn<<2], mi[mxn<<2];bool flip[mxn<<2];void pushdown( int i ) {if( flip[i] ) {swap( mx[ls], mi[ls] );swap( mi[rs], mx[rs] );mx[ls] = - mx[ls], mi[ls] = -mi[ls];mx[rs] = - mx[rs], mi[rs] = -mi[rs];flip[ls] ^= 1;flip[rs] ^= 1;flip[i] = 0;}}void build( int ll, int rr, int i ) {flip[i] = 0;if( ll == rr ) {mx[i] = w[ll];mi[i] = w[ll];return;}build( ll, md, ls ), build( md + 1, rr, rs );mx[i] = max( mx[ls], mx[rs] );mi[i] = min( mi[ls], mi[rs] );}void update( int x, int v, int ll, int rr, int i ) {if( ll == rr ) {mx[i] = v;mi[i] = v;return;}pushdown( i );if( x <= md )update( x, v, ll, md, ls );elseupdate( x, v, md + 1, rr, rs );mx[i] = max( mx[ls], mx[rs] );mi[i] = min( mi[ls], mi[rs] );}void ng( int l, int r, int ll, int rr, int i ) {if( ll == l && rr == r ) {swap( mx[i], mi[i] );mx[i] = - mx[i], mi[i] = -mi[i];flip[i] ^= 1;return;}pushdown( i );if( r <= md )ng( l, r, ll, md, ls );else if( l > md )ng( l, r, md + 1, rr, rs );elseng( l, md, ll, md, ls ),ng( md + 1, r, md + 1, rr, rs );mx[i] = max( mx[ls], mx[rs] );mi[i] = min( mi[ls], mi[rs] );}int query( int l, int r, int ll, int rr, int i ) {if( ll == l && rr == r ) return mx[i];pushdown( i );if( r <= md )return query( l, r, ll, md, ls );if( l > md )return query( l, r, md + 1, rr, rs );return max( query( l, md, ll, md, ls ), query( md + 1, r, md + 1, rr, rs ) );}int calc( int x, int y ) {int ret = - 0x3f3f3f3f;while( top[x] != top[y] ) {if( dep[top[x]] > dep[top[y]] )swap( x, y );ret = max( ret, query( tid[top[y]], tid[y], 1, n, 1 ) );y = fa[top[y]];}if( x != y ) {if( dep[x] > dep[y] )swap( x, y );ret = max( ret, query( tid[x] + 1, tid[y], 1, n, 1 ) );}return ret;}void NG( int x, int y ) {while( top[x] != top[y] ) {if( dep[top[x]] > dep[top[y]] )swap( x, y );ng( tid[top[y]], tid[y], 1, n, 1 );y = fa[top[y]];}if( x != y ) {if( dep[x] > dep[y] )swap( x, y );ng( tid[x] + 1, tid[y], 1, n, 1 );}}}go;int main() {//freopen( "tt.txt", "r", stdin );int n, cas;scanf( "%d", &cas );while( cas-- ) {scanf( "%d", &n );go.init( n );for( int i = 1; i < n; ++i ) {int u, v, c;scanf( "%d%d%d", &u, &v, &c );go.add( u, v, c );go.add( v, u, c );}go.cut();go.build( 1, n, 1 );char s[10];while( scanf( "%s", s ) && strcmp( s, "DONE" ) ) {if( s[0] == 'C' ) {int x, val;scanf( "%d%d", &x, &val );go.update( go.tid[is[x-1]], val, 1, n, 1 );}else {int a, b;scanf( "%d%d", &a, &b );if( s[0] == 'N' )go.NG( a, b );elseprintf( "%d\n", go.calc( a, b ) );}}}return 0;}


0 0