Gym 101142G Gangsters in Central City【思维+Lca】
来源:互联网 发布:英国大学精算 知乎 编辑:程序博客网 时间:2024/06/06 03:37
题目大意:
给出N个点的一棵树,有Q次操作,任何操作和查询都是对于叶子节点来说的。
每一次操作:
+ v表示点v来了盗贼,
- v表示点v的盗贼走了,
我们的根节点是1,和根节点1相连接的点都有水源,否则就没有了水源。
每次操作之后,查询:用最少的边数去切割树边,使得所有盗贼所在的点都没有水,于此同时,希望割除的方案使得无辜的城市的个数最少。
问最少边数和最少无辜城市的个数。
思路:
①我们知道,如果一个城市(v)有了盗贼,如果我们只贪心第一个点(最小割除边数)的话,我们直接删除与1节点直接相连的那个节点u(u是v的父亲/祖先),即可,那么最多割除的边数也就是与1号节点直接相连的点的个数。
②那么贪心第二个点,我们如果存在一个节点u(与1直接相连的点),其子树中的叶子节点被盗贼占领了若干个点,那么对应我们这条割边希望尽可能的向下去割,使得部分没有必要阻止水源的城市免收伤害。很显然,我们若找到了这些个被攻占的点的Lca的话,那么直接割除这个Lca上边的那条边即可。
我们知道,一颗子树中若干个节点的Lca,其实就是Dfs序最小的那个点,和Dfs序最大的那个点的Lca
那么接下来的任务就确定了,我们每一次查询的时候,求一下原来无辜的城市的个数,再求一下更新之后无辜的城市的个数,然后对应做差一下就能够知道多了多少个无辜的城市。对应加一下就行。
③每一次取最小最大Dfs序的点我们用set维护一下就行。
那么整体思路就是:预处理一下Dfs序,然后对于每个查询,
如果是节点u(与1直接相连的边)的子树中的第一个被攻占的点,那么ans++【类推相反,就是ans--】;
对于第二个查询,我们求一下原来情况下无辜城市的个数,然后更新一下求一下当前更新后无辜城市的个数,然后做差更新ans2即可。
Ac代码:
#include<stdio.h>#include<string.h>#include<vector>#include<algorithm>#include<math.h>#include<set>using namespace std;#define N 100000+5000void fre() { freopen("gangsters.in","r",stdin); freopen("gangsters.out","w",stdout);}set<int>ss[150000];vector<int>mp[150000];int cnt,tot;int n,m;int Id[150000];int Re[150000];int sum[150000];int belong[150000];int size[150000];int L[150000];int R[150000];void Dfs(int u,int from,int root){ int flag=0; size[u]=0; L[u]=++cnt; if(root!=0)belong[u]=root; for(int i=0;i<mp[u].size();i++) { int v=mp[u][i]; if(v==from)continue; flag=1; if(u!=1)Dfs(v,u,root); else Dfs(v,u,v); size[u]+=size[v]; } if(flag==0)size[u]=1,Id[u]=++tot,Re[tot]=u; R[u]=cnt;}/************************************/int p[150000][20];int d[150000];void dfs(int u,int from){ for(int i=0;i<mp[u].size();i++) { int v=mp[u][i]; if(v==from)continue; d[v]=d[u]+1; p[v][0]=u; dfs(v,u); }}void init(){ for(int j=1;(1<<j)<=n;j++) { for(int i=1;i<=n;i++) { p[i][j]=p[p[i][j-1]][j-1]; } }}int Lca(int x,int y){ if(d[x]>d[y])swap(x,y); int f=d[y]-d[x]; for(int i=0;(1<<i)<=f;i++) { if((1<<i)&f)y=p[y][i]; } if(x!=y) { for(int i=(int)log2(N);i>=0;i--) { if(p[x][i]!=p[y][i]) { x=p[x][i]; y=p[y][i]; } } x=p[x][0]; } return x;}/************************************/int main(){ fre(); while(~scanf("%d%d",&n,&m)) { cnt=0,tot=0; memset(L,0,sizeof(L)); memset(R,0,sizeof(R)); memset(Re,0,sizeof(Re)); memset(Id,0,sizeof(Id)); memset(sum,0,sizeof(sum)); memset(size,0,sizeof(size)); memset(belong,0,sizeof(belong)); for(int i=1;i<=n;i++)mp[i].clear(),ss[i].clear(); for(int i=2;i<=n;i++) { int x;scanf("%d",&x); mp[i].push_back(x); mp[x].push_back(i); } Dfs(1,-1,0);dfs(1,-1);init(); int A=0,B=0; while(m--) { char op[5]; int leaf; scanf("%s%d",op,&leaf); if(op[0]=='+') { if(sum[belong[leaf]]==0) { A++; ss[belong[leaf]].insert(Id[leaf]); sum[belong[leaf]]++; } else { int yuan=size[Lca(Re[*ss[belong[leaf]].begin()],Re[*--ss[belong[leaf]].end()])]-sum[belong[leaf]]; sum[belong[leaf]]++; ss[belong[leaf]].insert(Id[leaf]); int after=size[Lca(Re[*ss[belong[leaf]].begin()],Re[*--ss[belong[leaf]].end()])]-sum[belong[leaf]]; B+=after-yuan; } } else { if(sum[belong[leaf]]==1) { A--; ss[belong[leaf]].erase(Id[leaf]); sum[belong[leaf]]--; } else { int yuan=size[Lca(Re[*ss[belong[leaf]].begin()],Re[*--ss[belong[leaf]].end()])]-sum[belong[leaf]]; sum[belong[leaf]]--; ss[belong[leaf]].erase(Id[leaf]); int after=size[Lca(Re[*ss[belong[leaf]].begin()],Re[*--ss[belong[leaf]].end()])]-sum[belong[leaf]]; B+=after-yuan; } } printf("%d %d\n",A,B); } }}
- Gym 101142G Gangsters in Central City【思维+Lca】
- codeforces gym 101142G Gangsters in Central City
- Codeforces Gym 101142 G. Gangsters in Central City (最近公共祖先)
- 2016-2017 ACM-ICPC, NEERC, Northern Subregional Contest G - Gangsters in Central City
- GYM 100247 G. City Square(水~)
- GYM 100247 G. City Square(水~)
- GYM 101086 G.Paradise City(水~)
- Gym 100685G Gadget Hackwrench (LCA)
- Gym 100685G Gadget Hackwrench(LCA)
- Gym 100685G Gadget Hackwrench (LCA)
- GYM 100801D Distribution in Metagonia【思维】
- Gym 100685 G Gadget Hackwrench LCA+DFS标记
- Codeforces/gym/100685/problem/G Gadget Hackwrench ( LCA )
- 思维-Gym
- 2014-2015 ACM-ICPC, Central Europe Regional Contest (CERC 14) [Gym-100543G]
- codeforces gym 101142 F(思维)
- URAL 1409 Two Gangsters (开放思维)
- CodeForces Gym 100989G Mission in Amman (B)
- chroot ubuntu 16.04 on android
- 关于数组输入--类似于C那种动态分配数组内存的JAVA解决
- 大数据 第一节课 linux基础 基本的操作
- Jzoj3895 数字对
- Qt定时器的应用,实现时钟的状态
- Gym 101142G Gangsters in Central City【思维+Lca】
- 高级C语言教程-C语言函数setjmp()函数
- bzoj1731 [Usaco2005 dec]Layout 排队布局(差分约束+spfa)
- PHP最常用的设计模式
- Tensorflow实战Google-第三章-简单神经网络
- 【51nod】 1279
- NOIP专题训练——网络流 题解
- MyApplication框架或者变量的初始化
- < 笔记 > Python