G.Gangsters in Central City



题意:一棵树,节点1为根,是水源。水顺着边流至叶子。该树的每个叶子上有房子。有q个询问,一种为房子u被强盗入侵,另一种为强盗撤离房子u。对于每个询问,要求给出最小的阀门数来阻断水流向强盗所在房子,且在阀门数最小的情况下求最小的误伤房子数(即没被入侵却被断水的房子)。

思路:观察可发现,与根相连的子树都是独立的,因此有每有一颗这样的子树里有强盗,则ans1++,每有一颗这样的子树强盗全部撤离则ans1--;因此要维护的是误伤数ans2,我们对每一个与根相连的子树独立处理。要想最小化ans2,那阀门一定要设置在强盗所在房子的LCA的上边,则当前误伤数为该LCA为根的子树叶节点数减去强盗数,再减去原来的误伤数,即可用差值更新ans2。对于求某一子树内所有强盗的LCA,需要知道一个结论:若干个节点的LCA为其中dfs序最大与最小的两节点的LCA。因此可以开若干个set维护每个子树内强盗节点的dfs序。

#include<algorithm>
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<set>
#define dd(x) cout<<#x<<" = "<<x<<" "
#define de(x) cout<<#x<<" = "<<x<<endl
#define pb push_back
#define all(x) x.begin(),x.end()
using namespace std;
const int maxn=1e5+10;
int head[maxn],cnt=0;
struct Edge
{
int v,ne;
} edge[maxn<<1];
void add(int u,int v)
{
edge[++cnt].ne=head[u];
edge[cnt].v=v;
head[u]=cnt;
}
int tot=0,fa[maxn][32],dep[maxn],sz[maxn],id[maxn],rk[maxn];//sz记录叶节点数
vector<int> tree;
void dfs(int f,int u,int deep)
{
id[u]=++tot;
rk[tot]=u;
dep[u]=deep;
sz[u]=edge[head[u]].ne==0;
fa[u][0]=f;
if (f==1)
tree.pb(id[u]);
for (int i=1; i<=22; ++i)
fa[u][i]=fa[fa[u][i-1]][i-1];
for (int i=head[u]; i; i=edge[i].ne)
{
int v=edge[i].v;
if (v==f)
continue;
dfs(u,v,deep+1);
sz[u]+=sz[v];
}
}
int lca(int u,int v)
{
if (dep[u]<dep[v])
swap(u,v);
for (int i=22,d=dep[u]-dep[v]; i>=0; --i)
if (d&(1<<i))
u=fa[u][i];
if (u==v)
return u;
for (int i=22; i>=0; --i)
if (fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
}
set<int> st[maxn];
int gan[maxn],man[maxn];//gan为强盗数,man为误伤数
int main()
{
freopen("gangsters.in","r",stdin);
freopen("gangsters.out","w",stdout);
int n,q;
scanf("%d%d",&n,&q);
for (int i=2; i<=n; ++i)
{
int v;
scanf("%d",&v);
add(i,v);
add(v,i);
}
dfs(1,1,1);
int ans1=0,ans2=0;
while (q--)
{
char op[2];
int u;
scanf("%s%d",op,&u);
int num=upper_bound(all(tree),id[u])-tree.begin();//通过u的dfs序判断u在哪个子树内
if (op[0]=='+')
{
st[num].insert(id[u]);
int mn=*st[num].begin(),mx=*(--st[num].end()),a=lca(rk[mx],rk[mn]);
if (!gan[num])
ans1++;
gan[num]++;
ans2+=sz[a]-gan[num]-man[num];
man[num]=sz[a]-gan[num];
}
else
{
st[num].erase(lower_bound(all(st[num]),id[u]));
gan[num]--;
if (!gan[num])
{
ans1--;
ans2-=man[num];
man[num]=0;
}
else
{
int mn=*st[num].begin(),mx=*(--st[num].end()),a=lca(rk[mx],rk[mn]);
ans2+=sz[a]-gan[num]-man[num];
man[num]=sz[a]-gan[num];
}
}
printf("%d %d\n",ans1,ans2);
}
return 0;
}

2016 NEERC, Northern Subregional Contest G.Gangsters in Central City(LCA)的更多相关文章

  1. 2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest D:Distribution in Metagonia(构造)

    http://codeforces.com/gym/100801/attachments 题意:给出一个数n(1 <= n <= 1e18),将 n 拆成 m 个整数,其中 m 必须是 2 ...

  2. 模拟赛小结:2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest

    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest 2019年10月11日 15:35-20:35(Solved 8,Penalty 675 ...

  3. 2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest (9/12)

    $$2015-2016\ ACM-ICPC,\ NEERC,\ Northern\ Subregional\ Contest$$ \(A.Alex\ Origami\ Squares\) 签到 //# ...

  4. 【2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest D】---暑假三校训练

    2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest D Problem D. Distribution in Metagonia Input ...

  5. 2016 NEERC, Moscow Subregional Contest K. Knights of the Old Republic(Kruskal思想)

    2016 NEERC, Moscow Subregional Contest K. Knights of the Old Republic 题意:有一张图,第i个点被占领需要ai个兵,而每个兵传送至该 ...

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

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

  7. ACM ICPC 2016–2017, NEERC, Northern Subregional Contest Problem J. Java2016

    题目来源:http://codeforces.com/group/aUVPeyEnI2/contest/229510 时间限制:2s 空间限制:256MB 题目大意: 给定一个数字c 用 " ...

  8. 【题解】G.Graph(2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest)

    题目链接G题 题意 序列 \(a_1,a_2,⋯,a_n\) 是一个排列, 当且仅当它含有 1 到 n 的所有整数. 排列 \(a_1,a_2,⋯,a_n\) 是一个有向图的拓扑排序,当且仅当对于每条 ...

  9. 2017-2018 ACM-ICPC, NEERC, Northern Subregional Contest

    A. Auxiliary Project 完全背包. #include<stdio.h> #include<iostream> #include<string.h> ...

随机推荐

  1. 刚接触neo4j 问下 neo4j 生成的节点图形可以发布为纯网页方式么

    6 回复 pangguoming 1楼•3 年前 你是想要neo4j web控制端的可视化功能吗? 那是用D3.js 做的,你用前端用D3.js配合Java自己做 或者 去下载neo4j 的前端 开源 ...

  2. MongoDB实战读书笔记(一):JavaScript shell操作MongoDB

    1 基本增删改查 基本概念: 数据库:同关系型数据库 集合:类似关系型数据库的表 文档:类似关系型数据库的行 字段:类似关系型数据库的列 操作: insert:新增,若新增数据的主键已经存在,则会抛异 ...

  3. MySQL去除查询结果重复值

    下面先来看看例子: table  id name  1 a  2 b  3 c  4 c  5 b 库结构大概这样,这只是一个简单的例子,实际情况会复杂得多. 比如我想用一条语句查询得到name不重复 ...

  4. ItemsControl使用1

    <ItemsControl ItemsSource="{Binding DataItemsSource}"> //绑定一个List <ItemsControl.I ...

  5. sonarqube执行命令遇上的小问题

    在安装好sonarqube,本地或是服务器上都是可疑正常运行的情况下. 这一次我重新上传,修改配置SonarQube.Analysis.xml,sonar.host.url的值已经改为服务器上的,执行 ...

  6. 网络编程之NIO

    传统的BIO(Blocking IO)的缺点: 1.基于阻塞式IO建立起来的,导致服务端一直阻塞等待着客户端发起请求,如果客户端不发起,服务端的的业务线程会一直存. 2.弹性伸缩能力差,线程数和客户端 ...

  7. jQuery 手写菜单(ing)

    菜单支持多级 直接上代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset=&q ...

  8. JS数组判断,方法

    怎么判断一个对象是不是数组? 首先可以用 ES5 提供的 isArray 方法进行判断(注意:Array.isArray是ES 5.1推出的,不支持IE6~8,所以在使用的时候也应注意兼容问题. ) ...

  9. Django—跨域请求

    同源策略 首先基于安全的原因,浏览器是存在同源策略这个机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性. 而如果我们要跳过这个策略,也就是说非要跨域请求,那么就需要通过J ...

  10. windows下虚拟python环境

    Windows虚拟环境 cd %HOMEDRIVE%%HOMEPATH%\Desktop python3  -m  venv venv 环境变量修改脚本bat,把脚本放到%HOMEDRIVE%%HOM ...