POJ3237树链剖分

CHANGE i vChange the weight of the ith edge to v
NEGATE a bNegate the weight of every edge on the path from a to b
QUERY a bFind the maximum weight of edges on the path from a to b

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
	public static void main(String[] args) {
		new Task().solve() ;
	}
}

class Task {
	InputReader in = new InputReader(System.in);
	PrintWriter out = new PrintWriter(System.out);
	
	int[] size , top , son ;
	int[] dep , tid , fa , rank ;
	int dfn , edge ; 
	int[] head , to , next ;
	
	void addEdge(int u , int v){
		to[edge] = v ; next[edge] = head[u] ; head[u] = edge++ ;
		to[edge] = u ; next[edge] = head[v] ; head[v] = edge++ ;
	}
	
	void findHeavyEdge(int u , int father , int depth){
		dep[u] = depth ; 
		fa[u] = father ;
		size[u] = 1 ;
		for(int i = head[u] ; i != -1 ; i = next[i]){
			int v = to[i] ;
			if(v != father){
				findHeavyEdge(v , u , depth+1) ;
				size[u] += size[v] ;
				if(son[u] == -1 || size[v] > size[son[u]])
					son[u] = v ; 
			}
		}
	}
	
	void connectHeavyEdge(int u , int tp){
		top[u] = tp ;
		tid[u] = ++dfn ; 
		rank[tid[u]] = u ;
		if(son[u] == -1) return ;
		connectHeavyEdge(son[u] , tp) ;
		for(int i = head[u] ; i != -1 ; i = next[i]){
			int v = to[i] ;
			if(v != son[u] && v != fa[u])
				connectHeavyEdge(v , v) ;
		}
	}
	
	int[] max , min , lazy , val ; 
	
	void up(int t){
		max[t] = Math.max(max[t<<1] , max[t<<1|1]) ;
		min[t] = Math.min(min[t<<1] , min[t<<1|1]) ;
 	}
	
	void negate(int t){
		int tm = -max[t] ;
		max[t] = -min[t] ;
		min[t] = tm ;
	}
	
	void down(int t){
		if(lazy[t] != 0){
			lazy[t<<1] ^= 1 ;
			negate(t<<1) ;
			lazy[t<<1|1] ^= 1 ;
			negate(t<<1|1) ;
			lazy[t] = 0 ;
		}
	}
	
	void build(int l , int r , int t){
		lazy[t] = 0 ;
		if(l == r){
			max[t] = min[t] = val[l] ;
			return ; 
		}
		int m = (l + r) >> 1 ;
		build(l , m , t<<1) ;
		build(m+1 , r , t<<1|1) ;
		up(t) ;
	}
	
	int query(int L , int R , int l , int r , int t){
		if(L <= l && r <= R) return max[t] ;
		down(t) ;
		int m = (l + r) >> 1 ;
		int res = Integer.MIN_VALUE ;
		if(L <= m) res = Math.max(res , query(L, R, l, m, t<<1)) ;
		if(R > m)  res = Math.max(res , query(L, R, m+1, r, t<<1|1)) ;
		up(t) ;
		return  res ; 
	}
	
	void doChange(int i , int v , int l , int r , int t){
		if(l == r){
			max[t] = min[t] = v ;
			return ; 
		}
		down(t) ;
		int m = (l + r) >> 1 ;
		if(i <= m) doChange(i, v, l, m, t<<1) ;
		else doChange(i, v, m+1, r, t<<1|1) ;
		up(t) ;
	} 
	
	void updateByNegate(int L , int R , int l , int r , int t){
		if(L <= l && r <= R){
			negate(t) ;
			lazy[t] ^= 1 ; 
			return ; 
		}
		down(t) ;
		int m = (l + r) >> 1 ; 
		if(L <= m) updateByNegate(L, R, l, m, t<<1) ;
		if(R > m) updateByNegate(L, R, m+1, r, t<<1|1) ;
		up(t) ;
	} 
	
	void doNegate(int x , int y , int n){
		while(top[x] != top[y]){
			if(dep[top[x]] < dep[top[y]]){
				x ^= y ; y ^= x ; x ^= y ;
			}
			updateByNegate(tid[top[x]], tid[x] , 1, n, 1) ;
			x = fa[top[x]] ;
		}
		if(x == y) return  ;
		if(dep[x] > dep[y]){
			x ^= y ; y ^= x ; x ^= y ;
		}
		updateByNegate(tid[son[x]], tid[y], 1, n, 1) ; 
	}
	
	int change(int x , int y , int n){
		if(x == y) return 0 ; 
		int t = Integer.MIN_VALUE ;
		while(top[x] != top[y]){
			if(dep[top[x]] < dep[top[y]]){
				x ^= y ; y ^= x ; x ^= y ;
			}
			t = Math.max(t, query(tid[top[x]], tid[x] , 1, n, 1)) ;
			x = fa[top[x]] ;
		}
		if(x == y) return t ;
		if(dep[x] > dep[y]){
			x ^= y ; y ^= x ; x ^= y ;
		}
        t = Math.max(t , query(tid[son[x]], tid[y], 1, n, 1)) ; 
	    return t ; 
	}
	
	class Line{
		int u , v , w ;
		Line(int u , int v , int w){
			this.u = u ; 
			this.v = v ;
			this.w = w ; 
		}
	}
	
	Line[] lines ; 
	
	void init(int n){
		size = new int[n+1] ;
		top = new int[n+1] ;
		son = new int[n+1] ;
		dep = new int[n+1] ;
		tid = new int[n+1] ;
		fa = new int[n+1] ;
		rank = new int[n+1] ;
		head = new int[n+1] ;
		to = new int[n<<1|1] ;
		next = new int[n<<1|1] ;
		Arrays.fill(head , -1) ;
		Arrays.fill(son , -1) ;
		dfn = edge = 0 ;
		
		val = new int[n+1] ;
		max = new int[n<<2] ; 
		min = new int[n<<2] ;
		lazy = new int[n<<2] ; 
		
		lines = new Line[n+1] ;
	}
	
	void solve(){
		int t = in.nextInt() ; 
		while(t-- > 0){
			int n = in.nextInt() ; 
			init(n) ;
			for(int i = 1 ; i < n ; i++){
			   lines[i] = new Line(in.nextInt() , in.nextInt() , in.nextInt())	;
			   addEdge(lines[i].u , lines[i].v) ;
			}
			findHeavyEdge(1 , -1 , 0) ;
			connectHeavyEdge(1 , 1) ;
			
			for(int i = 1 ; i < n ; i++){
				if(tid[lines[i].u] < tid[lines[i].v]){
					lines[i].u ^= lines[i].v ;
					lines[i].v ^= lines[i].u ;
					lines[i].u ^= lines[i].v ;
				}
				val[tid[lines[i].u]] = lines[i].w ;	
			}
			
			build(1, n, 1) ;
			
			while(true){
				String type = in.next() ;
				if("DONE".equals(type)) break  ;
				if("QUERY".equals(type)) 
					 out.println(change(in.nextInt() , in.nextInt() , n)) ;
				else if("CHANGE".equals(type))
					 doChange(tid[lines[in.nextInt()].u], in.nextInt() , 1, n, 1) ;
				else doNegate(in.nextInt(), in.nextInt(), n) ;	
			}
			out.flush() ; 
		}
	}
}

class InputReader {
	public BufferedReader reader;
	public StringTokenizer tokenizer;

	public InputReader(InputStream stream) {
		reader = new BufferedReader(new InputStreamReader(stream), 32768);
		tokenizer = new StringTokenizer("");
	}

	private void eat(String s) {
		tokenizer = new StringTokenizer(s);
	}

	public String nextLine() {
		try {
			return reader.readLine();
		} catch (Exception e) {
			return null;
		}
	}
 
	public boolean hasNext() {
		while (!tokenizer.hasMoreTokens()) {
			String s = nextLine();
			if (s == null)
				return false;
			eat(s);
		}
		return true;
	}

	public String next() {
		hasNext();
		return tokenizer.nextToken();
	}

	public int nextInt() {
		return Integer.parseInt(next());
	}

	public long nextLong() {
		return Long.parseLong(next());
	}

	public double nextDouble() {
		return Double.parseDouble(next());
	}

	public BigInteger nextBigInteger() {
		return new BigInteger(next());
	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值