题目大意:有一棵$n(n\leqslant10^6)$个点的树,上面所有点是黑点,有$m$次操作:

  1. $C\;u$:把点$u$颜色翻转
  2. $G$:问树上最远的两个黑点的距离,若没有黑点输出$0$

题解:有两个点集,已知它们的直径的端点,可以很快求出点集的并的直径。所有可以用线段树维护所有点的直径。

卡点:考试时没想到

C++ Code:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <vector>
const int maxn = 1e5 + 10, inf = 0x3f3f3f3f; int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxn << 1];
inline void addedge(int a, int b) {
e[++cnt] = (Edge) { b, head[a] }; head[a] = cnt;
e[++cnt] = (Edge) { a, head[b] }; head[b] = cnt;
} int n, m;
int Col[maxn]; int dep[maxn], idx;
int LG[maxn << 1], pos[maxn], st[22][maxn << 1], tot;
inline int _min(int a, int b) { return dep[a] < dep[b] ? a : b; }
inline int _max(int a, int b) { return dep[a] > dep[b] ? a : b; }
void dfs(int u, int fa = 0) {
st[0][++tot] = u, pos[u] = tot;
for (int i = head[u], v; i; i = e[i].nxt) {
v = e[i].to;
if (v != fa) {
dep[v] = dep[u] + 1;
dfs(v, u);
st[0][++tot] = u;
}
}
}
inline int LCA(int x, int y) {
static int l, r, len; l = pos[x], r = pos[y];
if (l > r) std::swap(l, r);
len = LG[r - l + 1];
return _min(st[len][l], st[len][r - (1 << len) + 1]);
}
inline int dis(int x, int y) {
return dep[x] + dep[y] - 2 * dep[LCA(x, y)];
} struct Line {
int l, r;
Line() { }
Line(int _l, int _r) : l(_l), r(_r) { }
inline friend bool operator ! (const Line &rhs) {
return !rhs.l && !rhs.r;
}
inline Line operator + (const Line rhs) const {
if (!*this) return rhs;
if (!rhs) return *this;
const int x = rhs.l, y = rhs.r;
int now = dis(l, r), t; Line ans(l, r);
t = dis(l, x); if (now < t) now = t, ans = Line(l, x);
t = dis(l, y); if (now < t) now = t, ans = Line(l, y);
t = dis(r, x); if (now < t) now = t, ans = Line(r, x);
t = dis(r, y); if (now < t) now = t, ans = Line(r, y);
t = dis(x, y); if (now < t) now = t, ans = Line(x, y);
return ans;
}
} ;
namespace SgT {
Line V[maxn << 2];
void modify(int rt, int l, int r, int p, int v) {
if (l == r) {
V[rt] = Line(v, v);
return ;
}
const int mid = l + r >> 1;
if (p <= mid) modify(rt << 1, l, mid, p, v);
else modify(rt << 1 | 1, mid + 1, r, p, v);
V[rt] = V[rt << 1] + V[rt << 1 | 1];
}
int query() {
return dis(V[1].l, V[1].r);
}
} int num;
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
std::cin >> n; num = n;
for (int i = 1, a, b; i < n; ++i) {
std::cin >> a >> b;
addedge(a, b);
}
dfs(1); LG[0] = -1;
for (int i = 1; i <= tot; ++i) LG[i] = LG[i >> 1] + 1;
for (int i = 1; i <= LG[tot]; ++i)
for (int j = 1, len = 1 << i; j + len - 1 <= tot; ++j)
st[i][j] = _min(st[i - 1][j], st[i - 1][j + (len >> 1)]);
for (int i = 1; i <= n; ++i) SgT::modify(1, 1, n, i, i);
std::cin >> m;
while (m --> 0) {
char op;
std::cin >> op;
if (op == 'C') {
static int x;
std::cin >> x;
Col[x] ^= 1;
if (Col[x]) SgT::modify(1, 1, n, x, 0), --num;
else SgT::modify(1, 1, n, x, x), ++num;
} else {
if (!num) std::cout << "-1\n";
else std::cout << SgT::query() << '\n';
}
}
return 0;
}

  

最新文章

  1. Nginx在线服务状态下平滑升级或新增模块的详细操作
  2. C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 访问频率限制功能实现、防止黑客扫描、防止恶意刷屏
  3. File API 读取文件小结
  4. FMX 讯息框 FrameDialog
  5. Leetcode 26 Remove Duplicates from Sorted Array STL
  6. How To Tune or Test PLSQL Code Performance in Oracle D2k Forms
  7. C++学习(四)
  8. 再次探究Android ListView缓存机制
  9. Javascript进阶篇——浏览器对象—JavaScript计时器
  10. nodejs iconfont处理
  11. golang中container/heap包源码分析
  12. 我眼中的 Nginx(三):Nginx 变量和变量插值
  13. 线上CPU100%排查
  14. C++ Opencv createTrackbar()创建滑动条实现对比度、亮度调节及注意事项
  15. vue.js的计算机属性学习
  16. 手动上传图片到nginx下可访问,程序上传后访问图片报403
  17. Win10系统中VirtualBox桥接时找不到网卡的问题
  18. etcd 命令行(转)
  19. Maven学习笔记(十二)-maven打包之resource配置
  20. ASP.NET Web API 框架研究 Web Host模式下的消息处理管道

热门文章

  1. 【数据结构】Java版
  2. 小数据池/is和==/再谈编码作业
  3. Flask報錯 KeyError &#39;SQLALCHEMY_TRACK_MODIFICATIONS&#39;.md
  4. Beta冲刺(5/5)
  5. 从0开始部署GPU集群-1:k8s部署生态
  6. Linux:读取文件,每行拆分,并比较拆分数组长度
  7. arcgis python脚本工具实例教程—栅格范围提取至多边形要素类
  8. python开发笔记-字典按值排序取前n个key值
  9. java对压缩文件进行加密,winrar和好压 直接输入解密密码来使用
  10. Docker CentOS / Ubuntu容器开启 SSH 服务