题意:

树的根节点为水源,编号为 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. onenet基础通信套件加B300移植

    1. 遇到的第一个问题,说是少了文件,但是明明有这个文件的啊? scons: warning: Ignoring missing SConscript 'build_scons\arm\Hi2115\ ...

  2. RTL8188EUS之MAC地址烧写(使用利尔达模组)

    1. 手上有几个RTL8188EUS的wifi模块,打算把台式机装个无线网卡,但是插上之后发现没有MAC,没办法只能自己去找个烧写MAC的软件.RTL8188内部有个eFuse,用来配置之类的.这个e ...

  3. JavaWeb——JavaWeb开发入门

    一.基本概念 1.1.WEB开发的相关知识 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: 静态web资源( ...

  4. KubeCon深度洞察 | KubeEdge开源首秀

    以下内容根据华为云DJ在KubeCon Shanghai Demo Session演讲实录整理而成. KubeEdge Demo Show 11月15日上午Huawei宣布了KubeEdge项目开源, ...

  5. 接口测试工具postman(八)上传文件接口

    涉及到选择文件的接口,在[Body]页签下,key选择File选项,会显示“选择文件”按钮,选择本地的文件

  6. lintcode166 链表倒数第n个节点

    链表倒数第n个节点 找到单链表倒数第n个节点,保证链表中节点的最少数量为n. 思路:设置两个指针first,second指向head,first指针先向前走n,然后两个指针一起走,first指针走到末 ...

  7. 关于excle导数据的一些代码笔记

    package com.bonc.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutpu ...

  8. ubuntu ssh配置

    Secure Shell (SSH) is a cryptographic network protocol for operating network services securely over ...

  9. linux服务器操作小技巧

    python程序后台一直运行,并将打印信息输出到文件中 nohup -u test.py > out.txt & -u 表示无缓冲,直接将打印信息输出带文件中 &表示程序后台运行

  10. Leetcode - 461. Hamming Distance n&=(n-1) (C++)

    1. 题目链接:https://leetcode.com/problems/hamming-distance/description/ 2.思路 常规做法做完看到评论区一个非常有意思的做法.用了n&a ...