您的位置:首页 > 其它

POJ 3237 Tree 树链剖分

2014-08-18 15:55 344 查看
#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 );
		else
			update( 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 );
		else
			ng( 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 );
				else
					printf( "%d\n", go.calc( a, b ) );
			}
		}
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: