Split The Tree

Posted tian-luo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Split The Tree相关的知识,希望对你有一定的参考价值。

Split The Tree

时间限制: 1 Sec  内存限制: 128 MB

题目描述

You are given a tree with n vertices, numbered from 1 to n. ith vertex has a value wi
We define the weight of a tree as the number of different vertex value in the tree.
If we delete one edge in the tree, the tree will split into two trees. The score is the sum of these two trees’ weights.
We want the know the maximal score we can get if we delete the edge optimally.

 

输入

Input is given from Standard Input in the following format:
n
p2 p3  . . . pn
w1 w2  . . . wn
Constraints
2 ≤ n ≤ 100000 ,1 ≤ pi < i
1 ≤ wi ≤ 100000(1 ≤ i ≤ n), and they are integers
pi means there is a edge between pi and i

 

输出

Print one number denotes the maximal score.

 

样例输入

3
1 1
1 2 2

 

样例输出

3

 

来源/分类

2018东北四省赛 


 

题意:每颗树的重量定义为这颗树上所有节点权值不同的个数,现在要割掉一条边,求生成的两颗树最大的重量和。

做法:dfs序,然后枚举每一条边,删除这条边就相当于在dfs序中取走了一个区间,问题就变成了求区间不同数的个数。取走一个区间后,剩下的两块区间求不同数个数可以通过把区间加长一倍来做。

技术分享图片
#include<bits/stdc++.h>
#define N 100050
using namespace std;

vector<int>edge[N];
int w[N];
int children[N]={0},number[N]={0},dfsorder[N],len=0;

int dfs(int x)
{
    dfsorder[++len]=x;
    number[x]=len;
    children[x]=1;

    int Size=edge[x].size();
    for(int i=0;i<Size;i++)
    if(number[edge[x][i]]==0)
    {
        children[x]+=dfs(edge[x][i]);
    }
    return children[x];
}

struct ss
{
    int l,r,index,ans;

    bool operator < (const ss& s) const
    {
        return r<s.r;
    }
};
vector<ss>interval;

int c[2*N+5]={0};
void updata(int x,int v)
{
    for(int i=x;i<2*N;i+=i&(-i))c[i]+=v;
}

int Sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=c[x];
        x-=x&(-x);
    }
    return ans;
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=2;i<=n;i++)
    {
        int p;
        scanf("%d",&p);
        edge[i].push_back(p);
        edge[p].push_back(i);
    }

    for(int i=1;i<=n;i++)scanf("%d",&w[i]);

    dfs(1);

    for(int i=1;i<=n;i++)
    {
       interval.push_back((ss){number[i],number[i]+children[i]-1,i,0});
       interval.push_back((ss){number[i]+children[i],n+number[i]-1,i,0});
    }
    for(int i=1;i<=n;i++)
    {
        dfsorder[i]=w[dfsorder[i]];
        dfsorder[n+i]=dfsorder[i];
    }
    sort(interval.begin(),interval.end());

    int last[N]={0};
    int c1=1;

    for(int i=0;i<2*n;i++)
    {
        if(interval[i].l>interval[i].r)continue;

        for(int j=c1;j<=interval[i].r;j++)
        {
            if(last[dfsorder[j]]==0)
            {
                updata(j,1);
                last[dfsorder[j]]=j;
            }
            else
            {
                updata(last[dfsorder[j]],-1);
                updata(j,1);
                last[dfsorder[j]]=j;
            }
        }
        interval[i].ans=Sum(interval[i].r)-Sum(interval[i].l-1);
        c1=interval[i].r+1;
    }

    int sum[N]={0},ans=0;

    for(int i=0;i<2*n;i++)
    {
        sum[interval[i].index]+=interval[i].ans;
        ans=max(ans,sum[interval[i].index]);
    }

    printf("%d
",ans);
    return 0;
}
View Code

 

以上是关于Split The Tree的主要内容,如果未能解决你的问题,请参考以下文章

Solution: 题解 CF1059E Split the Tree

CF 1039D You Are Given a Tree && CF1059E Split the Tree 的贪心解法

我的Android进阶之旅解决:The currently selected variant “debug“ uses split APKs, but none of the 1 split...

我的Android进阶之旅解决:The currently selected variant “debug“ uses split APKs, but none of the 1 split...

环境初始化 Build and Install the Apache Thrift IDL Compiler Install the Platform Development Tools(代码片段

maven web项目的web.xml报错The markup in the document following the root element must be well-formed.(代码片段