zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    May 24th 2017 Week 21th Wednesday
    May 23rd 2017 Week 21st Tuesday
    全球顶尖大学的UX课程资源,英文!
    如何设计出一款出色的结账表单
    快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力
    界面设计中如何增强CTA按钮召唤力?
    10个实用的UX设计作品推销小窍门
    UX术语详解:任务流,用户流,流程图以及其它全新术语
    让你不再恋家的9款小众时尚的酒店网站设计
    聊聊原型设计中的团队管理功能
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9594262.html
Copyright © 2011-2022 走看看