题意:

树的根节点为水源,编号为 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. 北京Uber优步司机奖励政策(3月2日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. java String matches 正则表达

    package test; /** * 在String的matches()方法,split()方法中使用正则表达式. * @author fhd001 */ public class RegexTes ...

  3. 【vps搬家】--总结--费元星

    20150310  费元星 稍微玩VPS/服务器比较久的站长手中应该不止一台VPS,我们会有多台机器之间的相互使用.比如可能会遇到的是数据传输,我们传统的做法是先用FTP下载数据A到本地,然后再到本地 ...

  4. 「国庆训练」Bomb(HDU-5934)

    题意 给定\(n\)个炸弹,每个炸弹的坐标与代价与影响范围给定,炸弹会引爆影响范围内其他所有炸弹.求引爆所有炸弹的最小代价. 分析 先做\(n^2\)的循环,然后建图,对\(i\)能引爆\(j\)建边 ...

  5. XSS----payload,绕过,xss小游戏记录

    一.XSS 1.原理:攻击者把恶意的脚本代码注入到网页中,等待其他用户浏览 这些网页(或触发其他条件),从而执行其中的恶意代码. 1.xss实例代码: test.html <!DOCTYPE h ...

  6. Linux命令应用大词典-第6章 文件处理

    6.1 sort:对文件中的数据进行排序 6.2 uniq:将重复行从输出文件中删除 6.3 cut:从文件每行中输出选定的字节.字符或字段 6.4 comm:逐行比较两个已经排序的文件 6.5 di ...

  7. 基于Python的接口自动化

    第一步 Python的安装配置 打开官网: https://www.python.org/downloads/ 目前官网上已经更新到3.6.1啦,有两个版本,大家可以按自己喜欢的去下载,我自己选择的是 ...

  8. 初学Direct X(6)

    初学Direct X(6) 这一文本应和上一篇放在一起的,但是上一章写着写着发现对Draw绘制透明位图的方式有感觉了,决定就单写一篇,留作笔记了. 那这一篇是记录如何使用位图表来绘制动画帧,想象一下, ...

  9. Struts2(八.添加用户多张照片实现文件上传功能)

    1.modify.jsp 在modify.jsp修改用户信息页面实现文件上传,添加用户照片的功能 如果是文件上传,method必须是post,必须指定enctype <form method=& ...

  10. MATLAB画图符号标注

    线型 说明 标记符 说明 颜色 说明 - 实线(默认) + 加号符 r 红色 -- 双划线 o 空心圆 g 绿色 : 虚线 * 星号 b 蓝色 :. 点划线 . 实心圆 c 青绿色 x 叉号符 m 洋 ...