题面

Bzoj

Sol

做个转化
最开始都是虚边
操作\(1\)就是\(LCT\)里的\(Access\)操作
求的就是路径上虚边的个数+1

然后就好办了
用树链剖分+线段树来维护每个点到根虚边的个数的最大值
操作\(1\):\(Access\)时虚实边的转换,要把原来连的点的\(Splay\)的最左边的点在原树中的子树所有点+1,再把现在连的点做同样的操作-1
操作\(2\):单点查询,记\(deep[x]\)为\(x\)到根的虚边个数,那么答案就是\(deep[x]+deep[y]-2*deep[lca]+1\)
操作\(3\):子树最大值

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(2e5 + 5);IL ll Input(){RG ll x = 0, z = 1; RG char c = getchar();for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);return x * z;
}int size[_], Fa[_], deep[_], top[_], son[_], dfn[_], Index, ed[_], id[_];
int fst[_], nxt[_], to[_], cnt, n, m;
int ch[2][_], fa[_];
int mx[_ << 2], tag[_ << 2];IL void Add(RG int u, RG int v){nxt[cnt] = fst[u]; to[cnt] = v; fst[u] = cnt++;
}# define lson x << 1, l, mid
# define rson x << 1 | 1, mid + 1, rIL void Build(RG int x, RG int l, RG int r){if(l == r){mx[x] = deep[id[l]];return;}RG int mid = (l + r) >> 1;Build(lson); Build(rson);mx[x] = max(mx[x << 1], mx[x << 1 | 1]);
}IL void Modify(RG int x, RG int l, RG int r, RG int L, RG int R, RG int v){if(L <= l && R >= r){tag[x] += v, mx[x] += v;return;}RG int mid = (l + r) >> 1;if(L <= mid) Modify(lson, L, R, v);if(R > mid) Modify(rson, L, R, v);mx[x] = max(mx[x << 1], mx[x << 1 | 1]) + tag[x];
}IL int Query(RG int x, RG int l, RG int r, RG int L, RG int R){if(L <= l && R >= r) return mx[x];RG int mid = (l + r) >> 1, ans = 0;if(L <= mid) ans = Query(lson, L, R);if(R > mid) ans = max(ans, Query(rson, L, R));return ans + tag[x];
}# undef lson
# undef rsonIL void Dfs1(RG int u){size[u] = 1;for(RG int e = fst[u]; e != -1; e = nxt[e]){if(size[to[e]]) continue;fa[to[e]] = Fa[to[e]] = u, deep[to[e]] = deep[u] + 1;Dfs1(to[e]);size[u] += size[to[e]];if(size[to[e]] > size[son[u]]) son[u] = to[e];}
}IL void Dfs2(RG int u, RG int Top){dfn[u] = ++Index, top[u] = Top, id[Index] = u;if(son[u]) Dfs2(son[u], Top);for(RG int e = fst[u]; e != -1; e = nxt[e])if(!dfn[to[e]]) Dfs2(to[e], to[e]);ed[u] = Index;
}IL int LCA(RG int u, RG int v){while(top[u] ^ top[v]){if(deep[top[u]] > deep[top[v]]) swap(u, v);v = Fa[top[v]];}return deep[u] > deep[v] ? v : u;
}IL int Son(RG int x){  return ch[1][fa[x]] == x;  }IL int Isroot(RG int x){  return ch[0][fa[x]] != x && ch[1][fa[x]] != x;  }IL int Find(RG int x){  while(ch[0][x]) x = ch[0][x]; return x;  } IL void Rotate(RG int x){RG int y = fa[x], z = fa[y], c = Son(x);if(!Isroot(y)) ch[Son(y)][z] = x; fa[x] = z;ch[c][y] = ch[!c][x]; fa[ch[c][y]] = y;ch[!c][x] = y; fa[y] = x;
}IL void Splay(RG int x){for(RG int y = fa[x]; !Isroot(x); Rotate(x), y = fa[x])if(!Isroot(y)) Son(x) ^ Son(y) ? Rotate(x) : Rotate(y);
}IL void Access(RG int x){for(RG int y = 0, ff; x; y = x, x = fa[x]){Splay(x);if(ch[1][x]) ff = Find(ch[1][x]), Modify(1, 1, n, dfn[ff], ed[ff], 1);if(y) ff = Find(y), Modify(1, 1, n, dfn[ff], ed[ff], -1);ch[1][x] = y;}
}int main(RG int argc, RG char* argv[]){n = Input(); m = Input(); Fill(fst, -1);for(RG int i = 1, x, y; i < n; ++i)x = Input(), y = Input(), Add(x, y), Add(y, x);Dfs1(1), Dfs2(1, 1), Build(1, 1, n);for(RG int i = 1; i <= m; ++i){RG int opt = Input(), x = Input(), y, ans = 0, lca;if(opt == 1) Access(x);else if(opt == 2){y = Input(), lca = LCA(x, y);ans = Query(1, 1, n, dfn[x], dfn[x]) + Query(1, 1, n, dfn[y], dfn[y]);ans -= 2 * Query(1, 1, n, dfn[lca], dfn[lca]);printf("%d\n", ans + 1);}else printf("%d\n", Query(1, 1, n, dfn[x], ed[x]) + 1);}return 0;
}

转载于:https://www.cnblogs.com/cjoieryl/p/8438227.html

Bzoj4817:[SDOI2017]树点涂色相关推荐

  1. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 629  Solved: 371 [Submit][Stat ...

  2. bzoj4817: [Sdoi2017]树点涂色

    震惊!LCT还能这么用! 这个颜色修改的特点是点到根 搜刮一下性质,颜色从根到某个点是分层次单调增的,而且同一个点的两个不同儿子不会有相同颜色,也就是相同颜色的点是树上自上往下的一条链 前面这些都是次 ...

  3. BZOJ 4817: [Sdoi2017]树点涂色

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 273  Solved: 164 [Submit][Stat ...

  4. BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)

    题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...

  5. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB [Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中 ...

  6. 【线段树】【LCT】【LCA】树点涂色(luogu 3703)

    树点涂色 luogu 3703 题目大意 给出一棵树,每个节点的初始颜色不同,做若干操作: 1.在一个点到根节点路径上染上一种新的颜色 2.查询一条路径上有多少种不同的颜色 3.查询一个点x,使该点到 ...

  7. [BZOJ4817]树点涂色

    第一个操作比较麻烦,但可以看出它和lct里的access操作差不多,所以可以利用lct的性质巧妙维护操作1 直接用lct维护树中同颜色的链(因为染色操作是从$x$染到根所以同颜色的点一定形成一条链), ...

  8. P3703-[SDOI2017]树点涂色【LCT,线段树】

    正题 题目链接:https://www.luogu.com.cn/problem/P3703 题目大意 nnn个点的一棵树开始所有点有不同的颜色,mmm次操作 将根节点到xxx节点的路径上染上一种新的 ...

  9. ​LeetCode刷题实战276:栅栏涂色

    算法的重要性,我就不多说了吧,想去大厂,就必须要经过基础知识和业务逻辑面试+算法面试.所以,为了提高大家的算法能力,这个公众号后续每天带大家做一道算法题,题目就从LeetCode上面选 ! 今天和大家 ...

最新文章

  1. 一文详解为什么Serverless比其他软件开发方法更具优势
  2. DataGridView使用小结
  3. Kettle使用_16 闭包Closure Generator树形数据
  4. C++ new delete(二)
  5. centos安装docker显示 No package docker-ce available
  6. 在Python中使用try-except-else是否是一种好习惯?
  7. 微软编程一小时--微软2014实习生招募编程模拟测试感想
  8. sqlserver数据库分组查询
  9. Java 多维数组 三维数组 初始化 赋值 打印
  10. zend studio html插件安装,Zend Studio使用教程:将Zend Studio作为插件安装
  11. Ensp教程 —— Ensp模拟器中的设备如何连接到真实物理机
  12. 计算机中怎样算2的21次方,脑筋急转弯:2的31次方与3的21次方哪个大?天才知道!...
  13. linux磁珠技术,磁珠-china178-ChinaUnix博客
  14. 沙箱支付宝------简单实现支付
  15. vim中的删除键,复制键,粘贴键
  16. kylinserverv10部署dm8单实例命令行方式安装
  17. 微信小程序版 九宫格数独游戏
  18. 计算机专业选择福大还是南邮,48所院校考研历年报录比汇总,21考研可参考!...
  19. ARM 嵌入式系统开发 - 软件设计与优化
  20. 谷歌量子计算机_轰动全球的谷歌量子计算机

热门文章

  1. WinCE 开始菜单StartMenu_Create()函数代码分析
  2. VC++设置软件断点和“XXX已停止工作“对话框
  3. 使用jar命令查看搜索提取jar包中的文件
  4. 一些stl格式的点云的显示结果
  5. 看《你必须知道的.NET》有感--工厂模式的另类解读
  6. 找到数组中和为给定值的两个数
  7. VC++ VS2010 error LNK1123 转换到 COFF 期间失败 怎么办
  8. 关于 UDP Hole Punching 的资料
  9. 解决ECSHOP后台订单里面点击编辑配送方式时出现的警告问题
  10. stm32 usb 虚拟串口 相同_RTThread STM32 虚拟串口代码级移植