HDU 5893 List wants to travel(树链剖分+线段树)
2024-08-27 23:34:21
题目链接 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;
}
最新文章
- Service实时向Activity传递数据案例
- C#如何根据配置实现动态窗体
- 通过magento后台的magento connect安装magento extension
- AP模块的发票过账后关联对应的凭证编号。
- NoSQL架构实践(一)——以NoSQL为辅
- Spring IoC容器的设计—1—主线
- Java中的递归原理分析
- 5.JSON
- 单片AT89C2051 + SD卡 + 3310LCD = 音乐播放器
- Yahoo网站性能优化的34条军规
- 解决React通过ajax加载数据更新页面不加判断会报错的问题
- java知识点2
- Redis内存模型总结
- alert.log中的minact-scn: useg scan erroring out with error e:376警告
- Java:将数据库数据导出到Excel (一眼就看会)
- [转帖]你们知道LTE Cat.1到Cat.10 那Cat.0呢?
- iOS SDK 从配置文件里读SDK。转化成class 可同时加载多个SDK
- Hibernate 之主键生成策略小总结
- python 中hive 取日期时间的方法
- Geronimo 叛逆者: 使用集成软件包:Codehaus 的 Woodstox(转载)