题目链接:https://cn.vjudge.net/problem/Gym-101142G

知识点:  DFS序、LCA

题目大意:

  给定一棵有根树(根为 \(1\))。每次修改叶子节点会被染成黑色(最开始都是白色的),也可以被染回白色。给出 \(q\) 次修改,对每次修改问最少需要切断几条边就能保证黑色叶子不在树上,和保证用最少的切断数使得黑色叶子不在树上的前提下最少会有多少白色叶子与根的联系也被切断了。

解题思路:

  设根有 \(k\) 棵子树,除了根以外的所有结点都在这 \(k\) 棵子树中的一棵。

  第一个问题很容易解答:对于要被染成黑色的叶子,如果这个叶子所在的子树中已有其他黑色叶子,则答案不变,否则答案加一;对于要被染回白色的叶子,如果叶子所在子树中还有其他黑色叶子,则答案不变,否则答案减一。

  现在来解决第二个问题。其实,对于每一次修改,关键是如何找到这次修改的叶子所在子树剩下的所有黑色叶子的 \(LCA\)——用这个方法来解决这个难点:先预处理出树的 \(DFS\) 序,那么每次只要找到该子树中所有黑色叶子中 \(DFS\) 序最小和最大的两个点的 \(LCA\) 即可。(扩展到一般的情况:找树上的大于两个的结点的 \(LCA\),只需找这些结点中 \(DFS\) 序最小和最大的两个结点的 \(LCA\) 即可)。

AC代码:

 #include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+,DEG=; vector<int> G[MAXN];
int fa[MAXN][DEG];
int deg[MAXN]; int gfa[MAXN],have[MAXN];
void dfs2(int rt,int grandfa){
gfa[rt]=grandfa;
have[rt]=;
for(int i=;i<G[rt].size();i++){
int v=G[rt][i];
dfs2(v,grandfa);
have[rt]+=have[v];
}
if(!have[rt]) have[rt]=;
}
int tid=,dfs_id[MAXN],rid[MAXN];
void DFS(int rt){
dfs_id[rt]=tid++;
for(int i=;i<G[rt].size();i++){
int v=G[rt][i];
if(!dfs_id[v])
DFS(v);
}
}
void BFS(int root){
queue<int> que;
deg[root]=;
fa[root][]=root;
que.push(root);
while(!que.empty()){
int tmp=que.front();
que.pop();
for(int i=;i<DEG;i++)
fa[tmp][i]=fa[fa[tmp][i-]][i-];
for(int i=;i<G[tmp].size();i++){
int v=G[tmp][i];
if(v==fa[tmp][]) continue;
deg[v]=deg[tmp]+;
fa[v][]=tmp;
que.push(v);
}
}
}
int LCA(int u,int v){
if(deg[u]>deg[v]) swap(u,v);
int hu=deg[u],hv=deg[v];
int tu=u,tv=v;
for(int det=hv-hu,i=;det;det>>=,i++){
if(det&)
tv=fa[tv][i];
}
if(tu==tv) return tu;
for(int i=DEG-;i>=;i--){
if(fa[tu][i]==fa[tv][i])
continue;
tu=fa[tu][i];
tv=fa[tv][i];
}
return fa[tu][];
}
int used[MAXN];
set<int> ids[MAXN];
int last[MAXN];
int main(){
freopen("gangsters.in","r",stdin);
freopen("gangsters.out","w",stdout);
int n,q;
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++){
int p;
scanf("%d",&p);
G[p].push_back(i);
}
BFS();
DFS();
for(int i=;i<=n;i++)
rid[dfs_id[i]]=i;
for(int i=;i<G[].size();i++){
dfs2(G[][i],G[][i]);
have[]+=have[G[][i]];
} char od[];
int nd;
int ans1=,ans2=;
while(q--){
scanf("%s %d",od,&nd);
if(od[]=='+'){
used[gfa[nd]]++;
ids[gfa[nd]].insert(dfs_id[nd]);
if(used[gfa[nd]]==){
ans1++;
printf("%d %d\n",ans1,ans2);
continue;
}
}
else{
used[gfa[nd]]--;
ids[gfa[nd]].erase(dfs_id[nd]);
if(!used[gfa[nd]]){
ans1--;
printf("%d %d\n",ans1,ans2);
continue;
}
}
int l=*ids[gfa[nd]].begin(),r=*(--ids[gfa[nd]].end());
int t=LCA(rid[l],rid[r]);
ans2-=last[gfa[nd]];
last[gfa[nd]]=have[t]-used[gfa[nd]];
ans2+=last[gfa[nd]];
printf("%d %d\n",ans1,ans2);
} return ;
}

Gym101142G Gangsters in Central City的更多相关文章

  1. 2016 NEERC, Northern Subregional Contest G.Gangsters in Central City(LCA)

    G.Gangsters in Central City 题意:一棵树,节点1为根,是水源.水顺着边流至叶子.该树的每个叶子上有房子.有q个询问,一种为房子u被强盗入侵,另一种为强盗撤离房子u.对于每个 ...

  2. Codeforces Gym 101142 G Gangsters in Central City (lca+dfs序+树状数组+set)

    题意: 树的根节点为水源,编号为 1 .给定编号为 2, 3, 4, …, n 的点的父节点.已知只有叶子节点都是房子. 有 q 个操作,每个操作可以是下列两者之一: + v ,表示编号为 v 的房子 ...

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

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

  4. G. Gangsters in Central City

    给出一棵$1$为根节点的含$n$个节点的树,叶子节点都是房屋,在一个集合里面添加房屋和移除房屋. 每一次添加和移除后,回答下面两个问题. 1.  使得已选房屋都不能从根节点到达,最少需要砍多少条边. ...

  5. 2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest

    A. Anniversary Cake 随便挑两个点切掉就好了. #include<bits/stdc++.h> using namespace std; const int Maxn=2 ...

  6. sentence patterns

    第四部分     推理题 1.世界上每个角落的每个人都有立场,都有背景,都有推理性,能推理出一个人语言的真意,才成就了真正的推理能力: 2.换言之,如果你能通过一个人的说话推理出其身份职业,你的推理能 ...

  7. uva208 - Firetruck

    Firetruck The Center City fire department collaborates with the transportation department to maintai ...

  8. UVA208-Firetruck(并查集+dfs)

    Problem UVA208-Firetruck Accept:1733  Submit:14538 Time Limit: 3000 mSec  Problem Description The Ce ...

  9. Family Gathering at Christmas(思维题)

    Family Gathering at Christmas 时间限制: 1 Sec  内存限制: 128 MB提交: 13  解决: 4[提交] [状态] [讨论版] [命题人:admin] 题目描述 ...

随机推荐

  1. CF1285 --- Dr. Evil Underscores

    CF1285 --- Dr. Evil Underscores 题干 Today as a friendship gift, Bakry gave Badawy \(n\) integers \(a_ ...

  2. JavaScript HTMlL DOM对象(下)

    DOM:document operation model 文档操作模型 每个标签都是一个对象. 一.查找元素 DOM 回顾 直接查找 var obj = document.getElementById ...

  3. 对话Roadstar投资人:一家自动驾驶公司之死(三) ...

    11. Roadstar 如何收场? 雷锋网:你觉得 Roadstar 造成今天这样的局面,是什么导致的? 投资人代表 1:刚才我们也数次表达了,在每个人身上,可能每个人的诉求,不能达到同步,与公司的 ...

  4. 数据库SQL语言从入门到精通--Part 6--单表查询(快来PICK)

    数据库从入门到精通合集(超详细,学习数据库必看) 查询操作是SQL语言中很重要的操作,我们今天就来详细的学习一下. 一.数据查询的语句格式 SELECT [ALL|DISTINCT] <目标列表 ...

  5. TCP 可靠传输

    TCP报文段首部 序号: TCP是面向字节流的.在一个TCP连接中传送的字节流中的每一个字节都按顺序编号.整个要传送的字节流的起始序号必须在连接建立时设置.首部中的序号字段值则指的是本报文段所发送的数 ...

  6. RDP凭据离线脱取

    内网渗透-获取本地RDP密码 获取RDP 连接记录: reg query "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Clie ...

  7. Navicat,SQL注入,pymysql模块

    # 关键字exists(了解) 只返回布尔值 True False 返回True的时候外层查询语句执行 返回False的时候外层查询语句不再执行 select * from emp where exi ...

  8. 【Swift】获取UILabel中点击的某个功能标签文字并作出响应动作

    1.需求 首先.针对UILabel中显示的多个功能标签,作出颜色标记提示. 其次.对关键字作出点击响应动作. 如图所示: 解决: 1.使用正则匹配到关键字 public static var hash ...

  9. springmvc与struts2执行流程比较

    之前写过一篇struts2的执行流程的文章了,这里对struts2的流程就不做过多的分析,这篇文章主要分析spring-mvc的执行流程以 及struts2与spring-mvc的差别. 1.stru ...

  10. FreeAnchor:抛弃单一的IoU匹配,更自由的anchor匹配方法 | NIPS 2019

    论文抛弃以往根据IoU硬性指定anchor和GT匹配关系的方法,提出FreeAnchor方法来进行更自由的匹配,该方法将目标检测的训练定义为最大似然估计(MLE)过程,端到端地同时学习目标分类.目标检 ...