「ZJOI2007」捉迷藏
题目描述
给出一棵\(N\)个有色(黑白,黑色对应关灯,白色对应开灯)节点的树以及\(M\)次操作,每次操作将改变一个节点的颜色或者求出树上最远的两个白点距离
基本思路
\(60pts\)做法
这道题是动态点分治的板子题,动态点分治还是比(shi)较(fen)难写的。。。
所以我们先打一打部分分,瞄一眼数据范围:
对于\(\%60\)的数据,\(N\leq3000,M\leq10000\)
这样的数据很好做吧,我们用树的直径来搞就好了(还可以加一点卡常)。
求树的直径我用的是两次\(DFS\),不过我们要改一点细节:
int id, __max, co[MAXN];
//co维护单点颜色,0表示黑色,1表示白色
inline void dfs(int u, int fa, int dis) {
if (dis >= __max && !co[u]) __max = dis, id = u;
//只有当点u为黑点才可以更新
for (rg int v, i = head[u]; i; i = nxt[i])
if ((v = ver[i]) ^ fa) dfs(v, u, dis + 1);
}
这样就改好了,复杂度还是\(O(N)\)的。
在主函数里面,我们加一点这样的卡常:
因为这样的算法在执行修改时,只需\(O(1)\)修改\(co\)数组,而更新答案是\(O(N)\)的
所以我们只在每次查询时重新跑一遍\(DFS\)并且我们用一个变量\(flag\),表示我们是否求出了最新的结果,这样就算有连续多次查询我们也可以马上输出答案走人。
\(60pts\)参考代码
/*--------------------------------
Code name: HideAndSeek.cpp
Author: The Ace Bee
This code is made by The Ace Bee
--------------------------------*/
#include <queue>
#include <cstdio>
#include <algorithm>
#define rg register
using namespace std;
const int MAXN = 100010;
inline int read() {
int s = 0; bool f = false; char c = getchar();
while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
return f ? -s : s;
}
int n, m;
int tot, head[MAXN], nxt[MAXN << 1], ver[MAXN << 1];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }
int id, __max, co[MAXN];
inline void dfs(int u, int fa, int dis) {
if (dis >= __max && !co[u]) __max = dis, id = u;
for (rg int v, i = head[u]; i; i = nxt[i])
if ((v = ver[i]) ^ fa) dfs(v, u, dis + 1);
}
int main() {
n = read();
for (rg int u, v, i = 1; i <= n - 1; ++i)
u = read(), v = read(), Add_edge(u, v), Add_edge(v, u);
m = read(); char s[5]; bool flag = false;
for (rg int i = 1; i <= m; ++i) {
scanf("%s", s);
if (s[0] == 'C')
co[read()] ^= 1, flag = false;
else {
if (flag) printf("%d\n", __max);
else {
__max = 0, dfs(1, 0, 0);
__max = 0, dfs(id, 0, 0);
printf("%d\n", __max);
flag = true;
}
}
}
return 0;
}
\(100pts\)正解
上面也提到了,动态点分治难得写,所以我们还是打一发括号序列吧。
至于具体实现的话以及代码讲解的话,听说大家都是在一个地方,所以就不多赘述了(Orz 岛娘!!!)
那我可就直接上代码了(压行毒瘤qwq)
/*--------------------------------
Code name: HideAndSeek.cpp
Author: The Ace Bee
This code is made by The Ace Bee
--------------------------------*/
#include <cstdio>
#define rg register
const int INF = 2e9;
const int MAXN = 500010;
inline int max(int a, int b) { return a > b ? a : b ; }
inline int read() {
int s = 0; bool f = false; char c = getchar();
while (c < '0' || c > '9') f |= (c == '-'), c = getchar();
while (c >= '0' && c <= '9') s = (s << 3) + (s << 1) + (c ^ 48), c = getchar();
return f ? -s : s;
}
int tot, head[MAXN], nxt[MAXN << 1], ver[MAXN << 1];
inline void Add_edge(int u, int v)
{ nxt[++tot] = head[u], head[u] = tot, ver[tot] = v; }
int n, m, col[MAXN];
int black, len, s[MAXN * 3], pos[MAXN];
inline void dfs(int u, int fa) {
s[++len] = -1;
s[++len] = u, pos[u] = len;
for (rg int v, i = head[u]; i; i = nxt[i])
if ((v = ver[i]) ^ fa) dfs(v, u);
s[++len] = -2;
}
struct node{ int a, b, l1, l2, r1, r2, dis; }c[MAXN << 2];
inline int lc(int rt) { return rt << 1; }
inline int rc(int rt) { return rt << 1 | 1; }
inline void upt(int rt, int x) {
c[rt].a = c[rt].b = 0;
c[rt].l1 = c[rt].l2 = c[rt].r1 = c[rt].r2 = c[rt].dis = -1e9;
if (s[x] == -1) { c[rt].b = 1; return ; }
if (s[x] == -2) { c[rt].a = 1; return ; }
if (!col[s[x]]) c[rt].l1 = c[rt].l2 = c[rt].r1 = c[rt].r2 = c[rt].dis = 0;
}
inline void pushup(int rt) {
if (c[lc(rt)].b > c[rc(rt)].a)
c[rt].a = c[lc(rt)].a, c[rt].b = c[lc(rt)].b - c[rc(rt)].a + c[rc(rt)].b;
else
c[rt].a = c[lc(rt)].a - c[lc(rt)].b + c[rc(rt)].a, c[rt].b = c[rc(rt)].b;
c[rt].l1 = max(c[lc(rt)].l1, max(c[rc(rt)].l1 + c[lc(rt)].a - c[lc(rt)].b, c[rc(rt)].l2 + c[lc(rt)].a + c[lc(rt)].b));
c[rt].l2 = max(c[lc(rt)].l2, c[rc(rt)].l2 - c[lc(rt)].a + c[lc(rt)].b);
c[rt].r1 = max(c[rc(rt)].r1, max(c[lc(rt)].r1 - c[rc(rt)].a + c[rc(rt)].b, c[lc(rt)].r2 + c[rc(rt)].a + c[rc(rt)].b));
c[rt].r2 = max(c[rc(rt)].r2, c[lc(rt)].r2 + c[rc(rt)].a - c[rc(rt)].b);
c[rt].dis = max(max(c[lc(rt)].dis, c[rc(rt)].dis), max(c[lc(rt)].r1 + c[rc(rt)].l2, c[lc(rt)].r2 + c[rc(rt)].l1));
}
inline void build(int rt, int l, int r) {
if (l == r) { upt(rt, l); return ; }
int mid = (l + r) >> 1;
build(lc(rt), l, mid), build(rc(rt), mid + 1, r);
pushup(rt);
}
inline void update(int rt, int l, int r, int id) {
if (l == r) { upt(rt, l); return; }
int mid = (l + r) >> 1;
if (id <= mid) update(lc(rt), l, mid, id);
else update(rc(rt), mid + 1, r, id);
pushup(rt);
}
int main() {
black = n = read();
for (rg int u, v, i = 1; i <= n - 1; ++i)
u = read(), v = read(), Add_edge(u, v), Add_edge(v, u);
dfs(1, 0);
build(1, 1, len);
m = read();
char ss[5];
for (rg int i = 1; i <= m; ++i) {
scanf("%s", ss);
if (ss[0] == 'C') {
int x = read();
black += col[x] ? -1 : 1;
col[x] ^= 1, update(1, 1, len, pos[x]);
} else {
if (black == 0) puts("-1");
else if (black == 1) puts("0");
else printf("%d\n", c[1].dis);
}
}
return 0;
}
完结撒花\(qwq\)
「ZJOI2007」捉迷藏的更多相关文章
- 「ZJOI2007」「LuoguP1169」棋盘制作(并查集
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8×88 \times 88×8大小的黑白相间的方阵,对应八八六十四卦 ...
- LG1131 「ZJOI2007」时态同步 树形DP
问题描述 LG1131 题解 正难则反,把从一个点出发到叶子结点看做从叶子结点走到那个点. DP方程很显然. \(\mathrm{Code}\) #include<bits/stdc++.h&g ...
- LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链
问题描述 LG2272 BZOJ1093 题解 观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图. 此时存在的环可能会干扰求解,于是\(\mathrm{Tarjan}\)缩点. 于是 ...
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
随机推荐
- Django框架之Filters(过滤器)、母版的使用
在Django的模板语言中,通过使用 过滤器 来改变变量的显示. 过滤器的语法: {{ value|filter_name:参数 }} 使用管道符"|"来应用过滤器. 注意事项: ...
- Yii2框架 常用函数整合
1.使用事务添加数据: public function create() { if($this->validate()) { $trans = Yii::$app->db->begi ...
- lintcode算法周竞赛
------------------------------------------------------------第七周:Follow up question 1,寻找峰值 寻找峰值 描述 笔记 ...
- 关于ActiveMq的Exception occurred while processing this request, check the log for more information!问题
错误原因:jsp渲染的时候报错了.根本原因在于jdk版本和activemq版本的问题. 两种解决方案: 1.把jdk版本改为jdk1.7 2.activeMQ采用5.15,它依赖于jdk1.8
- linux 自带php切换xampp
查看系统中有哪些用户: cut -d : -f 1 /etc/passwd 查看当前php: which php 删除系统自带php软链 rm -rf /usr/bin/php 切换到PHP新路径 l ...
- 介绍Mobility Group
Mobility或Roaming是无线客户端能够安全地从一个AP无缝关联到另一个AP的能力,并且延迟尽可能的短. 当无线客户端和AP关联并通过AP进行身份验证时,注册AP的WLC会将客户端条目放在自己 ...
- 使用node查询数据库(mysql)时,日期格式不对的问题。
https://blog.csdn.net/chanlingmai5374/article/details/93190983 1.问题场景 数据库里存了 datetime.但 Node 查询出来是这样 ...
- 微信小程序开发豆瓣电影接口失效
豆瓣旧API接口停用,使用以下接口代替 .获取正在热映的电影:https://douban.uieee.com/v2/movie/in_theaters访问参数:start : 数据的开始项 coun ...
- P3378 (模板)并查集
使用带路径压缩的并查集,不然会TLE AC代码: #include <bits/stdc++.h> #define MP make_pair #define PB push_back #d ...
- 第八届极客大挑战 Web-iPhone X
题目: 解题思路: 第一次看到html里只有字其他啥也没有的题,一脸懵逼,学长提示抓包改包,于是开始我的苦逼解题. 0x01 抓包 0x02 改包 由于题目说只有iphoneX才能接受这个websit ...