题目描述

给出一棵\(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」捉迷藏的更多相关文章

  1. 「ZJOI2007」「LuoguP1169」棋盘制作(并查集

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8×88 \times 88×8大小的黑白相间的方阵,对应八八六十四卦 ...

  2. LG1131 「ZJOI2007」时态同步 树形DP

    问题描述 LG1131 题解 正难则反,把从一个点出发到叶子结点看做从叶子结点走到那个点. DP方程很显然. \(\mathrm{Code}\) #include<bits/stdc++.h&g ...

  3. LG2272/BZOJ1093 「ZJOI2007」最大半连通子图 Tarjan缩点+DAG求最长链

    问题描述 LG2272 BZOJ1093 题解 观察半联通的定义,发现图中的一些结点,构成的链一定是一个半联通子图. 此时存在的环可能会干扰求解,于是\(\mathrm{Tarjan}\)缩点. 于是 ...

  4. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  5. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  6. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  7. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  8. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  9. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

随机推荐

  1. Mac系统中桌面图片和用户头像图片的路径

    系统中的桌面图片: /Library/Desktop Pictures/ 用户头像图片: 根目录资源库/user pictures/ 参考: [https://bbs.feng.com/read-ht ...

  2. C:函数 注意点

    形参 在定义函数时指定的形参,在未出现函数调用时,它们并不占内存中的存储单元,因此称它们是形式参数或虚拟参数,简称形参,表示它们并不是实际存在的数据,所以,形参里的变量不能赋值. C不像C++里一样可 ...

  3. PL2303HXA自2012已停产

    解决"PL2303HXA自2012已停产,请联系供货商" USB不识别的问题: 问题是WIN10自带的驱动不兼容引起的,只能安装早期驱动,再驱动程序中选择旧版本驱动即可

  4. hadoop中block副本的放置策略

    下面的这种是针对于塔式服务器的副本的放置策略

  5. python3将json数据转换到excel中

    #!/usr/bin/env python# coding=utf-8# json转换为excel import xlrdimport jsonimport osfrom openpyxl impor ...

  6. try catch和if else

    当错误发生时,当事情出问题时,JavaScript 引擎通常会停止,并生成一个错误消息.描述这种情况的技术术语是:JavaScript 将抛出一个错误. try 语句允许我们定义在执行时进行错误测试的 ...

  7. SUDO_EDITOR

    目录 SUDO_EDITOR 参考 SUDO_EDITOR SUDO_EDITOR

  8. ASP.NET Core搭建多层网站架构【10-使用JWT进行授权验证】

    2020/01/31, ASP.NET Core 3.1, VS2019, Microsoft.AspNetCore.Authentication.JwtBearer 3.1.1 摘要:基于ASP.N ...

  9. JQ - 绑定(on)/解绑(off)事件(浅显的见解)

    on 绑定事件: $("selector").on("click",事件执行函数名); //为 selector 添加 点击事件 $("selecto ...

  10. CSS3绘制不规则图形,代码收集

    三角形系列(三角形.倒三角.左三角.右三角.左上三角.右上三角.左下三角.右下三角) 主要用到的是:宽度高度设置为0, border的各个边的设置(各个边的透明或不透明): .triangle-up ...