zoukankan      html  css  js  c++  java
  • HDU 5893 List wants to travel(树链剖分+线段树)

    题目链接 HDU5893

    $2016$年$ICPC$沈阳网络赛的$B$题。这道题其和 BZOJ2243 基本一样

    那道题我也写了题解 点这里

    两道题的区别就是$BZOJ$这题是点的权值,这道题是边权。

    所以我们把边权看成这条边连接的两个点的深度较大的那条边的点权就可以了。

    但是这样的话根结点就没有权值了。

    询问和查询的时候,若$x$和$y$的$LCA$为$t$,

    那么我们从$x$出发往上爬,爬到$X'$,使得$deep[X'] - deep[t] = 1$

    同样我们从$y$出发往上爬,爬到$Y'$,使得$deep[Y'] - deep[t] = 1$

    于是一个询问被我们拆成了两个,一个查询也被我们拆成了两个。

    然后依次处理就好了。

    当$x$是$y$的祖先,或者$y$是$x$的祖先的时候,特判下即可。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define rep(i, a, b)    for (int i(a); i <= (b); ++i)
    #define dec(i, a, b)    for (int i(a); i >= (b); --i)
    #define lson        i << 1, L, mid
    #define rson        i << 1 | 1, mid + 1, R
    #define MP        make_pair
    #define fi        first
    #define se        second
    
    typedef long long LL;
    typedef pair<int, int> PII;
    
    const int N = 5e4 + 10;
    const int A = 19;
    
    vector <PII> v[N];
    int father[N], deep[N], c[N], sz[N], son[N], f[N], top[N];
    int lazy[N << 2], s[N << 2], lc[N << 2], rc[N << 2];
    int st[N][A];
    int n, m, tot;
    char op[10];
    
    void dfs(int x, int fa, int dep, int val){
    	sz[x] = 1;
    	father[x] = fa;
    	deep[x] = deep[fa] + 1;
    	c[x] = val;
    
    	if (fa){ 
    		st[x][0] = fa;
    		for (int i = 0; st[st[x][i]][i]; ++i) st[x][i + 1] = st[st[x][i]][i];
    	}
    
    	for (auto cnt : v[x]){
    		int u = cnt.fi, w = cnt.se;
    		if (u == fa) continue;
    		dfs(u, x, dep + 1, w);
    		sz[x] += sz[u];
    		if (sz[son[x]] < sz[u]) son[x] = u;
    	}
    }
    
    void dfs2(int x, int tp){
    	f[x] = ++tot;
    	top[x] = tp;
    	if (son[x]) dfs2(son[x], tp);
    
    	for (auto cnt : v[x]){
    		int u = cnt.fi, w = cnt.se;
    		if (u == father[x] || u == son[x]) continue;
    		dfs2(u, u);
    	}
    }
    
    int LCA(int x, int y){
    	for (; top[x] ^ top[y]; ){
    		if (deep[top[x]] < deep[top[y]]) swap(x, y);
    		x = father[top[x]];
    	}
    
    	return deep[x] > deep[y] ? y : x;
    }
    
    inline int updis(int x, int dis){
    	dec(i, 17, 0) if ((1 << i) & dis) x = st[x][i], dis ^= (1 << i);
    	return x;
    }
    
    inline void pushup(int i){
    	lc[i] = lc[i << 1];
    	rc[i] = rc[i << 1 | 1];
    	if (rc[i << 1] ^ lc[i << 1 | 1]) s[i] = s[i << 1] + s[i << 1 | 1];
    	else s[i] = s[i << 1] + s[i << 1 | 1] - 1;
    }
    
    inline void pushdown(int i, int L, int R){
    	int tmp = lazy[i];
    	if (tmp == -1 || L == R) return;
    
    	s[i << 1]      = s[i << 1 | 1]    = 1;
    	lazy[i << 1]   = lazy[i << 1 | 1] = tmp;
    
    	lc[i << 1]     = rc[i << 1]       = tmp;
    	lc[i << 1 | 1] = rc[i << 1 | 1]   = tmp;
    	lazy[i] = -1;
    }
    
    void build(int i, int L, int R){
    	s[i] = 1;
    	lazy[i] = -1;
    
    	if (L == R) return;
    	int mid = (L + R) >> 1;
    
    	build(lson);
    	build(rson);
    }
    
    void change(int i, int L, int R, int l, int r, int val){
    	pushdown(i, L, R);
    	if (L == l && R == r){
    		lc[i] = rc[i] = val;
    		s[i]  = 1;
    		lazy[i] = val;
    		return;
    	}
    
    	int mid = (L + R) >> 1;
    	if (r <= mid) change(lson, l, r, val);
    	else if (l > mid) change(rson, l, r, val);
    	else{
    		change(lson, l, mid, val);
    		change(rson, mid + 1, r, val);
    	}
    
    	pushup(i);
    }
    
    int query(int i, int L, int R, int l, int r){
    	pushdown(i, L, R);
    	if (L == l && R == r) return s[i];
    
    	int mid = (L + R) >> 1;
    	if (r <= mid) return query(lson, l, r);
    	else if (l > mid) return query(rson, l, r);
    	else{
    		int tmp = 1;
    		if (rc[i << 1] ^ lc[i << 1 | 1]) tmp = 0;
    		return query(lson, l, mid) + query(rson, mid + 1, r) - tmp;
    	}
    }
    
    int getcolor(int i, int L, int R, int x){
    	pushdown(i, L, R);
    	if (L == R) return lc[i];
    	int mid = (L + R) >> 1;
    	if (x <= mid) return getcolor(lson, x);
    	else return getcolor(rson, x);
    }
    
    int solvesum(int x, int tp){
    	int ret = 0;
    	for (; top[x] ^ top[tp] ;){
    		ret += query(1, 1, n, f[top[x]], f[x]);
    		if (getcolor(1, 1, n, f[top[x]]) == getcolor(1, 1, n, f[father[top[x]]])) --ret;
    		x = father[top[x]];
    	}
    
    	ret += query(1, 1, n, f[tp], f[x]);
    	return ret;
    }
    
    void solvechange(int x, int tp, int val){
    	for (; top[x] ^ top[tp]; ){
    		change(1, 1, n, f[top[x]], f[x], val);
    		x = father[top[x]];
    	}
    
    	change(1, 1, n, f[tp], f[x], val);
    }
    
    int main(){
    
    	while (~scanf("%d%d", &n, &m)){
    		tot = 0;
    		rep(i, 0, n + 1) v[i].clear();
    		memset(st, 0, sizeof st);
    		memset(f, 0, sizeof f);
    		memset(father, 0, sizeof father);
    		rep(i, 2, n){
    			int x, y, z;
    			scanf("%d%d%d", &x, &y, &z);
    			v[x].push_back(MP(y, z));
    			v[y].push_back(MP(x, z));
    		}
    
    		memset(son, 0, sizeof son);
    		dfs(1, 0, 1, 0);
    		dfs2(1, 1);
    
    		memset(lc, 0, sizeof lc);
    		memset(rc, 0, sizeof rc);
    		build(1, 1, n);
    		rep(i, 2, n) change(1, 1, n, f[i], f[i], c[i]);
    		while (m--){
    			scanf("%s", op);
    			if (op[0] == 'Q'){
    				int x, y;
    				scanf("%d%d", &x, &y);
    				if (x == y){
    					puts("0");
    					continue;
    				}
    
    				if (deep[x] < deep[y]) swap(x, y);
    				int t = LCA(x, y);
    				if (y == t){
    					int yy = updis(x, deep[x] - deep[y] - 1);
    					printf("%d
    ", solvesum(x, yy));
    					continue;
    				}
    
    				int xx = updis(x, deep[x] - deep[t] - 1);
    				int yy = updis(y, deep[y] - deep[t] - 1);
    				int reta = solvesum(x, xx);
    				int retb = solvesum(y, yy);
    				int ret;
    				if (getcolor(1, 1, n, f[xx]) == getcolor(1, 1, n, f[yy]))
    					ret = reta + retb - 1;
    				else
    					ret = reta + retb;
    				printf("%d
    ", ret);
    			}
    
    			else{
    				int x, y, z;
    				scanf("%d%d%d", &x, &y, &z);
    				if (x == y) continue;
    
    				if (deep[x] < deep[y]) swap(x, y);
    				int t = LCA(x, y);
    				if (y == t){
    					int yy = updis(x, deep[x] - deep[y] - 1);
    					solvechange(x, yy, z);
    					continue;
    				}
    
    				int xx = updis(x, deep[x] - deep[t] - 1);
    				int yy = updis(y, deep[y] - deep[t] - 1);
    
    				solvechange(x, xx, z);
    				solvechange(y, yy, z);            
    
    			}
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    PAT (Advanced Level) 1086. Tree Traversals Again (25)
    PAT (Advanced Level) 1085. Perfect Sequence (25)
    PAT (Advanced Level) 1084. Broken Keyboard (20)
    PAT (Advanced Level) 1083. List Grades (25)
    PAT (Advanced Level) 1082. Read Number in Chinese (25)
    HDU 4513 吉哥系列故事――完美队形II
    POJ Oulipo KMP 模板题
    POJ 3376 Finding Palindromes
    扩展KMP
    HDU 2289 Cup
  • 原文地址:https://www.cnblogs.com/cxhscst2/p/7532940.html
Copyright © 2011-2022 走看看