当前位置: 首页 > news >正文

P7735 [NOI2021] 轻重边

P7735 [NOI2021] 轻重边

大意

给定两个点 \(a\)\(b\),首先对于 \(a\)\(b\) 路径上的所有点 \(x\)(包含 \(a\)\(b\)),你要将与 \(x\) 相连的所有边变为轻边。然后再将 \(a\)\(b\) 路径上包含的所有边变为重边。
给定两个点 \(a\)\(b\),你需要计算当前 \(a\)\(b\) 的路径上一共包含多少条重边。

思路

我们考虑一个小巧思。

我们将问题可以转化为将 \(a \to b\) 这条路径的点染上独一无二的颜色,最终求 \(a \to b\) 路径上的重边即为两端颜色相同的边的数量。

因为每次我们选的颜色都不一样,这样操作一定能够让我们通过只记录端点的颜色去统计这个值,我们通过直接维护区间的左右的端点的颜色和相邻重色的个数,我们如果区间的端点颜色重合就可以将这个答案继续累加。这个就是处理本题线段树的方式。

但是对于这个题目是在树上的操作,那就没什么说的了,直接树剖维护即可。但是如果你像我一样闲着没事的话可以用 LCT 维护,原因是这个更改 \(a \to b\) 路径的过程可以用 LCT 的 split 操作非常简便的完成。至于 LCT 里面维护的内容,和线段树几乎一样,剩下就没什么了。

代码

#include<iostream>
#include<algorithm>
using namespace std;#define lc(x) t[x].ch[0]
#define rc(x) t[x].ch[1]
#define fa(x) t[x].fa
const int MAXN = 1e5 + 5;struct node{int ch[2], fa;int col, tag;int lc, rc;int cnt; int sz;bool rev;node(){ch[1] = ch[0] = fa = 0;col = tag = lc = rc = cnt = sz = 0;rev = false;}
}t[MAXN];bool isroot(int x){return (lc(fa(x)) != x) && (rc(fa(x)) != x);
}void pushup(int x) {t[x].sz = t[lc(x)].sz + t[rc(x)].sz + 1;t[x].cnt = t[lc(x)].cnt + t[rc(x)].cnt;t[x].lc = lc(x) ? t[lc(x)].lc : t[x].col;t[x].rc = rc(x) ? t[rc(x)].rc : t[x].col;if(lc(x) && t[lc(x)].rc == t[x].col) t[x].cnt ++;if(rc(x) && t[rc(x)].lc == t[x].col) t[x].cnt ++;
}void update_rev(int x){if(!x) return;swap(lc(x), rc(x));swap(t[x].lc, t[x].rc);t[x].rev ^= 1;
}void apply_col(int x, int c){if(!x) return;t[x].col = t[x].lc = t[x].rc = t[x].tag = c;t[x].cnt = t[x].sz - 1;
}void pushdown(int x){if(t[x].rev){update_rev(lc(x));update_rev(rc(x));t[x].rev = 0;}if(t[x].tag){apply_col(lc(x), t[x].tag);apply_col(rc(x), t[x].tag);t[x].tag = 0;}
}void rotate(int x){int y = fa(x), z = fa(y);int k = (rc(y) == x);if(!isroot(y)) t[z].ch[rc(z) == y] = x;fa(x) = z;t[y].ch[k] = t[x].ch[k ^ 1];if (t[x].ch[k ^ 1]) fa(t[x].ch[k ^ 1]) = y;t[x].ch[k ^ 1] = y;fa(y) = x;pushup(y);pushup(x);
}void pushshell(int x){if(!isroot(x)) pushshell(fa(x));pushdown(x);
}void splay(int x){pushshell(x);while(!isroot(x)){int y = fa(x), z = fa(y);if(!isroot(y)) (rc(z) == y) ^ (rc(y) == x) ? rotate(x) : rotate(y);rotate(x);}
}void access(int x){for(int y = 0;x;y = x, x = fa(x)){splay(x);rc(x) = y;pushup(x);}
}void makeroot(int x){access(x);splay(x);update_rev(x);
}void split(int x, int y){makeroot(x);access(y);splay(y);
}void modify(int u, int v, int c){split(u, v);apply_col(v, c);
}void solve(){int n, m; cin >> n >> m;for(int i = 1;i <= n;i ++){t[i] = node();t[i].col = t[i].lc = t[i].rc = -i;t[i].sz = 1;}for(int i = 1;i < n;i ++){int u, v; cin >> u >> v;makeroot(u); fa(u) = v;}int cur_col = 0;while(m --){int op, u, v;cin >> op >> u >> v;if(op == 1){modify(u, v, ++ cur_col);split(u, v);apply_col(v, ++ cur_col);}else{split(u, v);cout << t[v].cnt << "\n";}}
}int main(){ios::sync_with_stdio(0);cin.tie(0);int T; cin >> T;while(T --) solve();return 0;
}
http://www.jsqmd.com/news/412288/

相关文章:

  • 2026国货之光!这些国产儿童鞋服品牌,宝妈必看 - 品牌测评鉴赏家
  • Spring Boot 3.5 + Spring AI 实战企业级智能问卷
  • 基于SpringBoot+Vue的高校大学生实习就业服务平台设计与实现
  • 2026宝妈必看!童装品牌红榜大公开~~ - 品牌测评鉴赏家
  • 宝妈宝爸必看!这些童装品牌美炸了 - 品牌测评鉴赏家
  • 2026年AI优化GEO公司Top9深度测评:从技术实力到效果落地的选型指南 - 小白条111
  • LangChain DeepAgents 速通指南(二)—— Summarization中间件为Agent作记忆加减法
  • 宝妈必看|6款热门童装羽绒服实测!避坑指南+实用分享,承包娃整个冬天的温暖 - 品牌测评鉴赏家
  • 敢签“70天无效退款”!奥本元NMN到底有什么底气终结抗衰骗局? - 资讯焦点
  • 2026最新十大知名板材品牌推荐榜!优质环保品质与高性价比源头厂家选择指南,适配多场景家居需求 - 十大品牌榜
  • react之shadcn(二)
  • 宝妈必看!2026高性价比童装品牌大揭秘 - 品牌测评鉴赏家
  • 英语月份命名为什么无规律?
  • wordpress上传图片无法显示
  • 2026宝妈必看!童装品牌红榜大公开 - 品牌测评鉴赏家
  • AI Agent的多任务并行处理能力开发
  • react之shadcn(一)
  • 宝妈宝爸必看!童装选购不迷路 - 品牌测评鉴赏家
  • 上海直饮水机一站式服务:详解服务体系+靠谱供应商推荐 - 小坤哥
  • 微信小程序个人主体的权限限制
  • 上海直饮水机供应商怎么选?专业科普+靠谱品牌推荐 - 小坤哥
  • 家族族谱生成制作创建管理H5抖音快手微信小程序看广告流量主开源
  • 宝妈宝爸看过来!这些婴童童装,萌娃穿了秒变街拍小达人 - 品牌测评鉴赏家
  • P15444 「IXOI R1」出题人完全不会给题目起名字
  • 【大数据毕设源码分享】基于hadoop+springboot的教材管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 0-16岁儿童鞋服闭眼入指南|8大宝藏品牌+分龄选购秘籍,宝妈抄作业! - 品牌测评鉴赏家
  • 宝妈必看!0-16岁儿童鞋服品牌红榜大公开 - 品牌测评鉴赏家
  • 【大数据毕设源码分享】基于Django+数据可视化的网络招聘信息的数据挖掘研究的设计与实现(程序+文档+代码讲解+一条龙定制)
  • 基于CASADI实现车道跟踪与动态避障的集成路径规划与控制系统研究附Matlab代码
  • 软考系统分析师90天冲刺|DAY02·需求获取技术全解析+5大方法+真题实战