G. Gangsters in Central City

1 gives a $ $ $ containing $ n-tree root node, leaf nodes are home, adding and removing houses inside houses in a set.

After each addition and removal, answer the following two questions.

1. do not make the selected houses from the root to reach the minimum number of edges need to cut.

2. At least $ 1 $ conditions asked to cut off the edge, how to make the cut edge from the start point node number of non-selected houses away can not reach the minimum, the minimum output.

To 100% of the data, $ 2 ≤ n ≤ 10 ^ 5, 1 ≤ q ≤ 10 ^ 5 $

Solution :  

  First observed that the first question the answer.

  Very easy to prove on a border is cut off all lawful $ u $ and even one side, which legitimate the $ u $ express both and $ 1 $ directly connected, and contains have been selected to be selected leaf node $ 1 $ directly son $ u $

  Obviously, this structure can cut off all selected houses.

  If it is not taken, there are in a selected sub-tree leaves, if not constructed as above, then in order to cut the selected leaves, trimming must be down, apparently, in order to ensure that the selected sub-tree leaves are cut off, then the number of broken edges must be incremented.

  All the first question, greedy strategy was established.

  On the basis of the first question to think about, we would like to further, if it finds a critical edge if cut underneath side so that the selected leaf node is cut off the number of sides is greater than 1, while the upper cut that edge is precisely cut off the leaf nodes can be selected, then the problem is solved.

  This is a critical edge in this sub-tree inside a leaf node is selected LCA collection and even a father's side.

  This is the second question of the greedy strategy.

  How to find a set of points LCA (the deepest common ancestor) in the trees it?

  The conclusion is: obtaining the minimum point of a sequence set point dfs $ u $, dfs sequence of a maximum point $ v $, then $ lca (u, v) $ is also desired.

  This is because the scope of dfs is a continuous sequence coverage range.

  Suppose there are three points, DFS sequence are a, p, b and a <p <b. So we assert LCA (a, p, b) = LCA (a, b).

  This is because: LCA two points, is the most recent of them contains points that range represents. Since LCA (a, b) comprises a section of a and b, it must also be included positioned between a and b p.

  Thus, for each of three arbitrary points, only need to store the maximum and minimum points DFS sequence. LCA is set at this point, i.e. at the entire set of LCA DFS minimum and maximum order of these two points DFS sequence.

So far, the theoretical part of this question is over, the next problem is to achieve.

It first obtains the subtree that corresponds zs [u] for each leaf belonging to the root node, for each node obtains its size [] represents the number of leaf nodes contain.

ret represents the number of leaf nodes currently being marked, ans1 represent the first question the answer, ans2 representing the total number of points covered above greedy strategy.

Obviously, the final answer is ans1, ans2 - ret;

For each sub-tree root node SET to open, the maintenance sequence which dfs labeled node, each requirement only to the maximum and minimum.

For each + and -, respectively, maintain the line (dynamic update ans1, ans2).

Complexity is $ (n log_2 n) O $ 

# include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct rec{ int pre,to; }a[N<<1];
int n,Q,dfn[N],tot,head[N],g[N][25],dep[N],size[N],zs[N],cnt[N];
struct node{ int x;};
bool operator < (node a,node b){return dfn[a.x]<dfn[b.x];}
set<node>st[N];
char s[10];
void adde(int u,int v)
{
    a[++tot].pre=head[u];
    a[tot].to=v;
    head[u]=tot;
}
void dfs1(int u,int fa)
{
    dfn[u]=++dfn[0]; g[u][0]=fa,dep[u]=dep[fa]+1; size[u]=0;
    bool leaf=1;
    for (int i=head[u];i;i=a[i].pre){
        int v=a[i].to; if (v==fa) continue;
        dfs1(v,u); leaf=0; size[u]+=size[v];
    }
    if (leaf) size[u]=1;
}
void dfs2(int u,int fa,int rt)
{
    bool leaf=1;
    for (int i=head[u];i;i=a[i].pre) {
        int v=a[i].to; if (v==fa) continue;
        dfs2(v,u,rt); leaf=0;
    }
    if (leaf) zs[u]=rt;
}
void init() {
    for (int i=1;i<=21;i++)
     for (int j=1;j<=n;j++)
      g[j][i]=g[g[j][i-1]][i-1];
}
int lca(int u,int v)
{
    if (dep[u]<dep[v]) swap(u,v);
    for (int i=21;i>=0;i--)
     if (dep[g[u][i]]>=dep[v]) u=g[u][i];
    if (u==v) return u;
    for (int i=21;i>=0;i--)
     if (g[u][i]!=g[v][i]) u=g[u][i],v=g[v][i];
    return g[u][0];
}
int main()
{
    freopen("gangsters.in","r",stdin);
    freopen("gangsters.out","w",stdout); 
    scanf("%d%d",&n,&Q);
    for (int i=2;i<=n;i++) {
        int u; scanf("%d",&u);
        adde(i,u); adde(u,i);
    }
    dfs1(1,0);init();
    for (int i=head[1];i;i=a[i].pre) dfs2(a[i].to,1,a[i].to);
    int ans1=0,ans2=0,ret=0;
    while (Q--) {
        int d; scanf("%s%d",s,&d);    
        if (s[0]=='+') {
            ret++;
            if (cnt[zs[d]]==0) ans1++;  cnt[zs[d]]++;
            int pre=0;
            if (st[zs[d]].size()!=0) {
                int u=(*(st[zs[d]].begin())).x,v=(*(--st[zs[d]].end())).x;
                pre=size[lca(u,v)];
            }
            st[zs[d]].insert((node){d});
            int u=(*(st[zs[d]].begin())).x,v=(*(--st[zs[d]].end())).x;
            int now=size[lca(u,v)];
            ans2+=now-pre;   printf("%d %d\n",ans1,ans2-ret);
        } else {
            ret--;
            if (cnt[zs[d]]==1) ans1--;  cnt[zs[d]]--;
            int u=(*(st[zs[d]].begin())).x,v=(*(--st[zs[d]].end())).x;
            int pre=size[lca(u,v)];
            st[zs[d]].erase((node){d});
            int now=0;
            if (st[zs[d]].size()!=0) {
                u=(*(st[zs[d]].begin())).x,v=(*(--st[zs[d]].end())).x;
                now=size[lca(u,v)];
            }
            ans2+=now-pre;  printf("%d %d\n",ans1,ans2-ret);
        }
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/ljc20020730/p/11260473.html