题目链接: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. QQ靓号资料空白且空间开通教程

    QQ靓号资料空白且空间开通教程 首先你需要两个QQ号第一个是普通QQ号第二个是去这个官方网站注册一个QQ免费靓号https://ssl.zc.qq.com/v3/index-chs.html?type ...

  2. 【集群实战】Rsync常见错误总结

    1. 服务端指定模块没有对应目录 报错详情: @ERROR: chdir failed rsync error: error startingclient-server protocol (code ...

  3. mysql查询连接数

    最近公司的测试服务器数据库经常是连接爆满,几次加大了依旧满了. 明明只有几个人在用这个数据库,但是连接数到了三四百.于是就想是谁一直开着连接不释放,于是写了个SQL查了下连接使用情况. SQL如下: ...

  4. SaaS 公司如何切入大客户

    编者按:本文作者是氪空间第四期项目 Kuick 创始人崔超,其现在的产品KuickDeal是一款销售活动管理工具.本文来自作者投稿,36 氪经授权转载. 首先,今天我们不讨论 SaaS 公司应该做中小 ...

  5. zabbix3.x.x升级教程

    1:停掉正在运行的zabbix服务,确保没有新数据写入数据库. /etc/init.d/zabbix_server stop 2:备份原zabbix的数据库数据,以及相关文件. mysqldump - ...

  6. OEL6 /boot分区删除恢复

    对linux的应用有一段时间来,虽然谈不上精通,但日常应用maintenance还是没问题的,昨天自己故意把/boot分区直接format了,今天来尝试恢复,看看自己对linux启动方面的认识如何,总 ...

  7. Binary Index Tree

    0 引言 Leetcode307 这道题给一个可变数组,求从\(i\)到\(j\)的元素之和. 一个naive的做法是,每次查询都从\(i\)累加到\(j\): class NumArray { pu ...

  8. [USACO1.5]回文质数 Prime Palindromes

    题目描述 因为151既是一个质数又是一个回文数(从左到右和从右到左是看一样的),所以 151 是回文质数. 写一个程序来找出范围[a,b](5 <= a < b <= 100,000 ...

  9. CF1324F Maximum White Subtree——换根dp

    换根dp,一般用来解决在无根树上,需要以每个节点为根跑一边dfs的dp问题 我们做两遍dfs 先钦定任意一个点为根 第一遍,算出\(f_i\)表示\(i\)的子树产生的答案,这里,子树指的是以我们钦定 ...

  10. P1353 Running S

    题意:https://www.luogu.com.cn/problem/P1353 奶牛们打算通过锻炼来培养自己的运动细胞,作为其中的一员,贝茜选择的运动方式是每天进行 n 分钟的晨跑.在每分钟的开始 ...