[洛谷P2056][ZJOI2007]捉迷藏(2019-7-20考试)
2024-10-20 21:01:12
题目大意:有一棵$n(n\leqslant10^6)$个点的树,上面所有点是黑点,有$m$次操作:
- $C\;u$:把点$u$颜色翻转
- $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;
}
最新文章
- Nginx在线服务状态下平滑升级或新增模块的详细操作
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 访问频率限制功能实现、防止黑客扫描、防止恶意刷屏
- File API 读取文件小结
- FMX 讯息框 FrameDialog
- Leetcode 26 Remove Duplicates from Sorted Array STL
- How To Tune or Test PLSQL Code Performance in Oracle D2k Forms
- C++学习(四)
- 再次探究Android ListView缓存机制
- Javascript进阶篇——浏览器对象—JavaScript计时器
- nodejs iconfont处理
- golang中container/heap包源码分析
- 我眼中的 Nginx(三):Nginx 变量和变量插值
- 线上CPU100%排查
- C++ Opencv createTrackbar()创建滑动条实现对比度、亮度调节及注意事项
- vue.js的计算机属性学习
- 手动上传图片到nginx下可访问,程序上传后访问图片报403
- Win10系统中VirtualBox桥接时找不到网卡的问题
- etcd 命令行(转)
- Maven学习笔记(十二)-maven打包之resource配置
- ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
热门文章
- 【数据结构】Java版
- 小数据池/is和==/再谈编码作业
- Flask報錯 KeyError &#39;SQLALCHEMY_TRACK_MODIFICATIONS&#39;.md
- Beta冲刺(5/5)
- 从0开始部署GPU集群-1:k8s部署生态
- Linux:读取文件,每行拆分,并比较拆分数组长度
- arcgis python脚本工具实例教程—栅格范围提取至多边形要素类
- python开发笔记-字典按值排序取前n个key值
- java对压缩文件进行加密,winrar和好压 直接输入解密密码来使用
- Docker CentOS / Ubuntu容器开启 SSH 服务