题目链接 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\n", 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\n", 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;
}

HDU 5893 List wants to travel(树链剖分+线段树)的更多相关文章

  1. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  2. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  10. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. Difference between x:Reference and x:Name

    {x:Reference ...} -> returns just a reference of an object it doesn't create that "bridge&qu ...

  2. helm istio k8s docker

    helm https://hub.helm.sh/ k8s https://www.kubernetes.org.cn/k8s istio 微服务 https://istio.io/

  3. Luogu P2664 树上游戏 dfs+树上统计

    题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...

  4. HashMap允许将null用作键 也允许将null作为值

    HashMap不能保证元素的顺序,HashMap能够将键设为null,也可以将值设为null. 与之对应的是Hashtable,(注意大小写:不是HashTable),Hashtable不能将键和值设 ...

  5. LeetCode 岛屿的最大面积

    给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着. 找到给定的二维数组中 ...

  6. zabbix:告警、恢复消息次数

    之前zabbix配置告警,存在告警信息发送多次并且恢复信息也跟着发送多次了,导致企业微信流量不够用,没有找到恢复信息单独的设置项 动作中的步骤我个人理解为:1-5的意思是发送5条告警消息      3 ...

  7. vue+axios+promise实际开发用法

    axios它是基于promise的http库,可运行在浏览器端和node.js中,然后作者尤雨溪也是果断放弃了对其官方库vue-resource的维护,直接推荐axios库,小编我也是从vue-res ...

  8. (转)TDD的iOS开发初步以及Kiwi使用入门

    本文转自“瞄神”博客 TDD的iOS开发初步以及Kiwi使用入门 测试驱动开发(Test Driven Development,以下简称TDD)是保证代码质量的不二法则,也是先进程序开发的共识.App ...

  9. LeetCode(95) Unique Binary Search Trees II

    题目 Given n, generate all structurally unique BST's (binary search trees) that store values 1-n. For ...

  10. React中css的使用

    网页的布局.颜色.形状等UI展示方式主要是由Css进行设置,在ReactJs中也是一样.ReactJs中的Css结构方式与传统的Web网页类似,但依然存在一些差异.ReactJs中Css文件本身的编写 ...