1. 程式人生 > >Gym 101142G Gangsters in Central City【思維+Lca】

Gym 101142G Gangsters in Central City【思維+Lca】

題意:

  • 給一棵樹,葉子節點為房子,q次操作,節點1為根節點(蓄水池)向房子供水
  • 每次操作有兩種型別,+ x 強盜佔領了編號為x的房子,- x強盜離開了編號為x的房子。
  • 對每次操作,ans1計算出最少卡住幾個節點使得強盜佔領的房子都沒水喝,ans2卡住這些點後沒有被強盜佔領的房子通不了水的數量最小,每次輸出這兩個數

思路:

  • 對根節點,如果有k個直接連線的點,拆成k棵子樹。每棵有強盜佔領的子樹肯定最多隻需要卡住一個點,那ans1就是k個子樹中有強盜的的子樹數量。
  • 對每棵子樹求出被強盜佔領的點dfs序最大的和最小的兩個點的lca就是這棵子樹中被強盜佔領的所有的點的lca。處理出每個節點下有多少個房子(sz[i]
    ),那麼求出lca後,先減去沒進行這次操作前這個子樹的貢獻,然後再加上這個操作,求出這顆子樹上的點的lca,再加上這棵子樹的貢獻。ans2=sz[lca]-強盜佔領的點

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for(int i=(s);i<(t);++i)
#define per(i,s,t) for(int i=((t)-1);i>=(s);--i)
#define pb push_back
#define dd(x) cout<<#x<<'='<<x<<' '
#define de(x) cout<<#x<<'='<<x<<'\n' #define fi first #define se second typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef vector<int> vi; const int N=1e6+5; int dp[N][20],n; vi G[N]; set<int>st[N]; //維護第i棵子樹中的dfs序 int tot,
ver[N*2],R[N*2],First[N*2],bel[N],sz[N],cut[N]; //cut[i] 第i棵子樹中強盜佔領的房子數量 //bel[i],節點i屬於那棵子數 // First[u] u節點的在ver中第一次出現的下標,即dfs序 bool vis[N]; void dfs(int u,int dep){ vis[u]=true;ver[++tot]=u;First[u]=tot;R[tot]=dep; rep(i,0,G[u].size()){ int v=G[u][i]; if(!vis[v]){ dfs(v,dep+1); ver[++tot]=u; R[tot]=dep; } } } void ST(){ rep(i,1,tot+1){ dp[i][0]=i; } for(int j=1;(1<<j)<=tot;++j){ for(int i=1;i+(1<<j)-1<=tot;++i){ int a=dp[i][j-1];http://codeforces.com/group/aUVPeyEnI2/contest/229510/attachments int b=dp[i+(1<<(j-1))][j-1]; if(R[a]<R[b])dp[i][j]=a; else dp[i][j]=b; } } } int RMQ(int l,int r){ int k=0; while(1<<(k+1)<=r-l+1){ k++; } int a=dp[l][k],b=dp[r-(1<<k)+1][k]; return R[a]<R[b]?a:b; } int LCA(int u,int v){ int res=RMQ(u,v); return ver[res]; } void Dfs(int u,int rt){ bel[u]=rt; vis[u]=true; if(G[u].size())sz[u]=0; else sz[u]=1; rep(i,0,G[u].size()){ int v=G[u][i]; if(!vis[v]){ Dfs(v,rt); sz[u]+=sz[v]; } } } int main() { tot=0; memset(vis,0,sizeof(vis)); memset(sz,0,sizeof(sz)); int q,p; scanf("%d%d",&n,&q); rep(i,2,n+1){ scanf("%d",&p); G[p].pb(i); } dfs(1,1); ST(); memset(vis,0,sizeof(vis)); rep(i,0,G[1].size()){ Dfs(G[1][i],i+1); } int ans1=0,ans2=0; char op[10]; int x,fa,mi,ma,lca; while(q--){ scanf("%s%d",op,&x); if(op[0]=='+'){ fa=bel[x]; if(cut[fa]){ mi=*st[fa].begin(),ma=*st[fa].rbegin(); lca=LCA(mi,ma); ans2-=sz[lca]-cut[fa]; } if(cut[fa]==0)ans1++; cut[fa]++; st[fa].insert(First[x]); mi=*st[fa].begin(),ma=*st[fa].rbegin(); lca=LCA(mi,ma); ans2+=sz[lca]-cut[fa]; } else{ fa=bel[x]; mi=*st[fa].begin(),ma=*st[fa].rbegin(); lca=LCA(mi,ma); ans2-=sz[lca]-cut[fa]; if(cut[fa]==1)ans1--; cut[fa]--; st[fa].erase(First[x]); if(cut[fa]){ mi=*st[fa].begin(),ma=*st[fa].rbegin(); lca=LCA(mi,ma); ans2+=sz[lca]-cut[fa]; } } printf("%d %d\n",ans1,ans2); } return 0; }