题意:

树的根节点为水源,编号为 1 。给定编号为 2, 3, 4, …, n 的点的父节点。已知只有叶子节点都是房子。

有 q 个操作,每个操作可以是下列两者之一:

  1. + v ,表示编号为 v 的房子被歹徒占领。
  2. - v ,表示歹徒退出编号为 v 的房子。

初始所有房子都没有歹徒。对于每次变化后,要求删除最少的边,使得所有有歹徒的房子均无法与水源连通;同时,在此基础上要求受影响的普通房子数量最少。

题解:

首先对树的根节点的子树分类,那么实际上最多删除的边就是子树个数。

对于每个子树,如果要求受影响的普通房子数量最少,那么其实就是求所有歹徒的房子的lca。

求这个lca,可以利用dfs序,选dfs序最小的那个结点和最大的那个结点求出的lca就是所有结点的lca(这个可以用set维护)

然后用树状数组维护有多少普通房子受到影响即可。

#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
#define fi first
#define se second
using namespace std;
typedef pair<int, int> PII;
const int maxn = 1e5 + ;
int c[maxn*], F[maxn][];
int deep[maxn], p[maxn][], col[maxn];
vector<int> G[maxn];
set<PII> S[maxn][];
int n, x, tot, q;
char str[];
PII ans;
void Modify(int x, int s){
for(; x <= *n; x += x&(-x)) c[x] += s;
}
int Query(int y){
if(y <= ) return ;
int ans = ;
for(int x = y; x; x -= x&(-x)) ans += c[x];
return ans;
}
int query(int x, int y) { return Query(y) - Query(x-); } int lca(int u, int v)
{
if(deep[u] > deep[v]) swap(u, v);
for(int i = ; i >= ; i--) if(deep[p[v][i]] >= deep[u]) v = p[v][i];
if(u == v) return u;
for(int i = ; i >= ; i--) if(p[v][i] != p[u][i]) u = p[u][i], v = p[v][i];
return p[u][];
} void dfs(int x, int fa, int d, int lab){
p[x][] = fa;
deep[x] = d;
col[x] = lab;
F[x][] = ++tot;
for(auto to : G[x]){
if(to == fa) continue;
dfs(to, x, d+, lab);
}
F[x][] = ++tot;
if(G[x].size() == ) { Modify(F[x][], ); Modify(F[x][], ); }
} void lca_pre(){
for(int j = ; j <= ; j++)
for(int i = ; i <= n; i++)
p[i][j] = p[p[i][j-]][j-];
} int main()
{
freopen("gangsters.in", "r", stdin);
freopen("gangsters.out", "w", stdout);
cin>>n>>q;
for(int i = ; i < n; i++){
scanf("%d", &x);
G[x].push_back(i+);
}
int coln = G[].size();
for(int i = ; i < G[].size(); i++)
dfs(G[][i], , , i+);
lca_pre();
int u, v, uv;
while(q--){
cin>>str;
if(str[] == '+'){
scanf("%d", &x);
if(S[col[x]][].size() == ) ans.fi++;
if(S[col[x]][].size() > ){
u = (*S[col[x]][].begin()).se; v = (*--S[col[x]][].end()).se;
uv = lca(u, v);
if(G[uv].size() != ) ans.se -= query(F[uv][], F[uv][])/;
}
S[col[x]][].insert({F[x][], x});
S[col[x]][].insert({F[x][], x});
Modify(F[x][], -);
Modify(F[x][], -); u = (*S[col[x]][].begin()).se; v = (*--S[col[x]][].end()).se;
uv = lca(u, v);
if(G[uv].size() != ) ans.se += query(F[uv][], F[uv][])/; printf("%d %d\n", ans.fi, ans.se);
} else {
scanf("%d", &x);
if(S[col[x]][].size() == ) ans.fi--; u = (*S[col[x]][].begin()).se, v = (*--S[col[x]][].end()).se;
uv = lca(u, v);
if(G[uv].size() != ) ans.se -= query(F[uv][], F[uv][])/; S[col[x]][].erase({F[x][], x});
S[col[x]][].erase({F[x][], x});
Modify(F[x][], );
Modify(F[x][], ); if(S[col[x]][].size() > ){
u = (*S[col[x]][].begin()).se, v = (*--S[col[x]][].end()).se;
uv = lca(u, v);
if(G[uv].size() != ) ans.se += query(F[uv][], F[uv][])/;
} printf("%d %d\n", ans.fi, ans.se);
}
}
return ;
}

Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)的更多相关文章

  1. Gym 101142G : Gangsters in Central City(DFS序+LCA+set)

    题意:现在有一棵树,1号节点是水源,叶子节点是村庄,现在有些怪兽会占领一些村庄(即只占领叶子节点),现在要割去一些边,使得怪兽到不了水源.给出怪兽占领和离开的情况,现在要割每次回答最小的割,使得怪兽不 ...

  2. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  3. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  4. Codeforces 570D TREE REQUESTS dfs序+树状数组 异或

    http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory li ...

  5. Codeforces 570D TREE REQUESTS dfs序+树状数组

    链接 题解链接:点击打开链接 题意: 给定n个点的树.m个询问 以下n-1个数给出每一个点的父节点,1是root 每一个点有一个字母 以下n个小写字母给出每一个点的字母. 以下m行给出询问: 询问形如 ...

  6. CodeForces 570D DFS序 树状数组 Tree Requests

    参考九野巨巨的博客. 查询一个子树内的信息,可以通过DFS序转成线形的,从而用数据结构来维护. #include <iostream> #include <cstdio> #i ...

  7. Codeforces Round #381 (Div. 2) D. Alyona and a tree dfs序+树状数组

    D. Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  8. Codeforces Round #381 (Div. 2) D dfs序+树状数组

    D. Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)

    The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...

随机推荐

  1. 【BZOJ5290】[HNOI2018]道路(动态规划)

    [BZOJ5290][HNOI2018]道路(动态规划) 题面 BZOJ 洛谷 题目直接到洛谷上看吧 题解 开始写写今年省选的题目 考场上我写了一个模拟退火骗了\(90\)分...然而重测后只剩下45 ...

  2. Java:泛型擦除

    https://docs.oracle.com/javase/tutorial/java/generics/erasure.html

  3. Altium designer18设置原理图尺寸

    1. AD18版本设置原理图尺寸和以前版本不一样,具体是在界面右侧Properties里面的Sheet Sizes.

  4. Qt-Qml-隐藏标题栏-程序依附任务栏

    最近换工作,直接欢动qml这边来了,以后可能会有更多关于qml的文章 今天第一个,qml下面怎么隐藏标题栏 第一种方法是在使用QQuickView加载qml文件的话,这里就可以使用QQuickView ...

  5. Selenium安装(二)

    安装python 安装Selenium之前首先来说一下Python,python是一门动态性语言,python的编写比较灵活,简洁,开发效率高.因此以python结合selenium来进行自动化测试. ...

  6. Ubuntu卡在logo界面

    对于这个问题,我也是在最近一次偶然的机会中发现的. 我重装了了Ubuntu 18.04, 很多东西需要重新配置,  有个刚性需求就是配置shadowsocks实现***,对于从windows向linu ...

  7. Android 修改系统默认density

    如你所知在Anroid N 中,系统添加了多个级别的密度值供用户选择. 系统的默认的值就是 ro.sf.lcd_density 同时其他级别的默认值的大小基础也是以默认值为基础,然后乘以不同的比例得到 ...

  8. 【paging_Class 分页类】使用说明

    类名:paging_Class 说明:分页类 注意: 1) 支持百万级数据分页 2) 支持多种类型的SQL语法,比如 Left Join 等. 3) 自动保存查询中的错误情况,记录保存在:/Cache ...

  9. 使用树莓派实现(山寨)高清视频叠加(HDMI OSD)

    项目需要在HDMI上叠加一些字符包括汉字和数值,要求不能使用台式机,本身也没有HDMI采集卡驱动开发能力,所以通过海思的HDMI编码器将HDMI编码为h.264网络视频流,然后通过树莓派解码显示,做字 ...

  10. HADOOP docker(七):hive权限管理

    1. hive权限简介1.1 hive中的用户与组1.2 使用场景1.3 权限模型1.3 hive的超级用户2. 授权管理2.1 开启权限管理2.2 实现超级用户2.3 实现hiveserver2用户 ...