[OpenJudge0054]特务会议召开

试题描述

在敌占区的特务时常会碰头。敌占区有n个城市,为保证安全,中央经过侦查,只选择了n-1条较安全的道路作为特务们碰头可以走的道路。每次开会,中央会选择特务正在工作当中的最早开始工作的那一个所在城市作为开会地点。为保证特务安全,开会时,中央会派安全小队在每一条特务会经过的道路上进行保护。每次开会时,中央想知道需要保护的道路共有多少条。

有时中央会认为一个城市很重要,于是在这个城市安插一个特务(即使该城已有特务);有时一个城市的敌人被干掉了,于是召回这个城市的特务(即使城中没有特务)。一开始中央还没有向敌占区派特务。

输入

第一行两个整数n,m,表示城市数和中央的命令数。
接下来n-1行,每行两个整数x和y,表示x和y间有一条特务可以通过的道路。
接下来m行,每行开头一个字符:
若为 + ,接下来一个数w,表示中央在w安插了一名特务。
若为 - ,接下来一个数w,表示城市w的特务全被召回。
若为 ?,表示特务会议召开,问有多少道路需要被保护。
(+,-与数之间有空格)

输出

对于每次特务会议召开,输出一行一个整数,表示需要被保护的道路数。

输入示例


+
+
+
?
-
?

输出示例


数据规模及约定

对于30%的数据,n<=1000,m<=1000;
对于100%的数据,n<=100000,m<=100000;

题解

借这道题学一下虚树的概念和性质。

不难发现这题我们只需要关心安有特务的点(不妨称之为特殊点),好的,那么我们将这些点提取出来,我们还需要关心他们的 lca,但是两两求 lca 显然是 n2 的;而我们又发现如果将这些点按照它们在树上的 dfs 序大小排个序,找相邻两个点的 lca 就好了。没错,这些 lca 和特殊点就构成了虚树。

性质 1:有不超过 2k 个节点(k 是特殊点个数)。显然 lca 个数小于 k,加起来小于 2k。

性质 2:相邻两个点的距离之和(包括第 1 个和最后一个特殊点)等于虚树大小的一半。这个也很显然,自己画画图就好了。

有了性质 2 这题就做完了。

搞个 set,懒得写平衡树了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <set>
using namespace std; int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
} #define maxn 100010
#define maxm 200010
#define maxlog 20
int n, q, m, head[maxn], nxt[maxm], to[maxm]; void AddEdge(int a, int b) {
to[++m] = b; nxt[m] = head[a]; head[a] = m;
swap(a, b);
to[++m] = b; nxt[m] = head[a]; head[a] = m;
return ;
} int Dfs[maxn], clo, Poi[maxn], Fa[maxlog][maxn], dep[maxn];
void build(int u, int fa) {
Dfs[u] = ++clo; Poi[clo] = u;
Fa[0][u] = fa;
for(int i = 1; i < maxlog; i++) Fa[i][u] = Fa[i-1][Fa[i-1][u]];
for(int e = head[u]; e; e = nxt[e]) if(to[e] != fa) {
dep[to[e]] = dep[u] + 1;
build(to[e], u);
}
return ;
} int calc(int a, int b) {
// printf("in calc: %d %d\n", a, b);
int ans = dep[a] + dep[b];
if(dep[a] < dep[b]) swap(a, b);
for(int i = maxlog - 1; i >= 0; i--)
if(dep[a] - dep[b] >= (1 << i)) a = Fa[i][a];
for(int i = maxlog - 1; i >= 0; i--)
if(Fa[i][a] != Fa[i][b]) a = Fa[i][a], b = Fa[i][b];
int c = a == b ? a : Fa[0][b];
ans -= (dep[c] << 1);
return ans;
} set <int> S;
std :: set <int> :: iterator it, it2; int main() {
n = read(); q = read();
for(int i = 1; i < n; i++) {
int a = read(), b = read();
AddEdge(a, b);
} build(1, 0);
// for(int i = 1; i <= n; i++) printf("(%d)%d ", i, Dfs[i]); putchar('\n');
// for(int i = 1; i <= n; i++) printf("%d ", Poi[i]); putchar('\n');
int ans = 0;
while(q--) {
char op[2]; scanf("%s", op);
if(op[0] == '+') {
int u = read();
if(S.count(Dfs[u])) continue;
if(S.size()) {
it = S.upper_bound(Dfs[u]);
int a = *it, b;
if(it == S.end()) a = *(S.begin());
if(it == S.begin()) {
it2 = S.end();
b = *(--it2);
}
else b = *(--it);
a = Poi[a]; b = Poi[b];
ans -= calc(a, b);
ans += calc(a, u); ans += calc(u, b);
}
S.insert(Dfs[u]);
}
if(op[0] == '-') {
int u = read();
if(!S.count(Dfs[u])) continue;
if(S.size()) {
it = S.upper_bound(Dfs[u]);
int a = *it, b;
if(it == S.end()) a = *(S.begin());
it = S.lower_bound(Dfs[u]);
if(it == S.begin()) {
it2 = S.end();
b = *(--it2);
}
else {
it2 = it;
b = *(--it2);
}
a = Poi[a]; b = Poi[b];
ans += calc(a, b);
ans -= calc(a, u); ans -= calc(u, b);
}
S.erase(Dfs[u]);
}
if(op[0] == '?') printf("%d\n", ans >> 1);
} return 0;
}
/*
13 1000
1 2
1 3
1 4
1 5
2 6
2 7
6 8
6 9
6 10
4 11
5 12
5 13
?
+ 13
?
+ 11
?
+ 9
?
*/

[OpenJudge0054]特务会议召开的更多相关文章

  1. [BZOJ3991][SDOI2015]寻宝游戏

    [BZOJ3991][SDOI2015]寻宝游戏 试题描述 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择 ...

  2. Syscan360会议胸牌破解揭秘

    Syscan360会议胸牌破解揭秘 背景 有幸参加今年11月份的上海Syscan360安全会议,会议期间有一个亮点就是360的独角兽团队设计了一款电子badge(胸牌)供参加人员进行破解尝试,类似于美 ...

  3. 会议管理心得记录(非markdown版)

    前提 本文说的会议特指有开发团队成员参与的会议, 包括但不限于开发.设计.测试.运维.管理岗位的成员. 因为不同工种和行业都有其特殊性,我是一名程序员,并不太了解其他工种和行业的具体情况,不敢妄言. ...

  4. 中国计算机学会CCF推荐国际学术会议

    中国计算机学会推荐国际学术会议 (计算机系统与高性能计算) 一.A类 序号 会议简称 会议全称 出版社 网址 1 ASPLOS Architectural Support for Programmin ...

  5. [Exchange 2013]创建约会和会议

    简介 会议和约会之间的重要区别是,会议有与会者,并且没有约会.约会和会议可以是单实例或属于重复序列,但与会者. 房间或资源中不包括约会,因为它们不需要发送一条消息.在内部,Exchange 使用相同的 ...

  6. Beta版总结会议

    一,设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的app要解决一个令人头痛但无人具体来实现的这一社会困扰现象.因为学生或者社会人士在参加竞 ...

  7. Alpha版总结会议

    昨天上课的时候,我们学习了项目总结这一部分的内容,并根据老师提供的项目Postmortem模板对我们的项目进行了总结. 项目Postmortem模板主要分为设想和目标.计划.资源.变更管理.设计和实现 ...

  8. 计应152第六组Sprint计划会议

    Sprint计划会议 会议时间:2016年12月8下午16:00 会议地点:宿舍 会议进程 • 首先我们讨论了排球计分规则程序完成需要做的一些工作:程序的初期设计,数据分析,典型用户,场景,代码的编写 ...

  9. Qcon会议之所见所想

    作为普通码农一枚,Qcon是俺参与过的最高级的技术大会了.大会共历时三天,因为俺第二天就得赶火车休个五一大长假,所以只参加了第一天4/25号的会议(其他俩天自然有其他同事会去观摩),不过第一天的会议有 ...

随机推荐

  1. php格式化金额函数分享

    /**  * 格式化金额 *  * @param int $money  * @param int $len  * @param string $sign  * @return string  */ ...

  2. 关于datatable linq的转换

    关于datatable datarow DataTable paraval = GetParaVal(DateCondition, strUrl, Page, RowPage, iYearMonthN ...

  3. url下载网页的三种方法

    # -*- coding: utf-8 -*- import cookielib import urllib2 url = "http://www.baidu.com" print ...

  4. Java之强引用、 软引用、 弱引用、虚引用

    1.强引用 平时我们编程的时候例如:Object object=new Object();那object就是一个强引用了.如果一个对象具有强引用,那就类似于必不可少的生活用品,垃圾回收器绝不会回收它. ...

  5. 自然语言7_NLTK中文语料库sinica_treebank

    http://www.hankcs.com/program/python/nltk-chinese-corpus-sinica_treebank.html NLTK包含Sinica (中央研究院)提供 ...

  6. pyinstaller 官方介绍

    http://www.pyinstaller.org/ pyinstaller支持多个平台,windows,linux,mac,兼容多个第三方包,包括pyqt,django,matplotlib Py ...

  7. ubuntu14.04安装了im-switch后系统设置中不见了语言支持

    sudo apt-get install language-selector-gnome

  8. 轻取帝国CMS管理员密码

    “帝国”CMS是一套著名的PHP整站程序,是国内使用人数最多的PHPCMS程序之一.令人无奈的是,“帝国”虽然把势力壮大了,却忽略了自身防护的建设,结果在黑客攻击下,“帝国”沦陷了.“帝国”CMS曝出 ...

  9. SSL、OPENSSL、SSH、OPENSSH

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议.TLS与 ...

  10. verilog描述表决器的两种方式简易分析

    命题:设计一个三变量表决器.真值表如下: 可以写出并简化得出公式:F=AB+BC+AC. 以下是两种算法: 第一种:仅从算法方面描述为:A.B.C的和大于1则输出结果为1,否则为0:源码如下: mod ...