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]={},number[N]={},dfsorder[N],len=; int dfs(int x)
{
dfsorder[++len]=x;
number[x]=len;
children[x]=; int Size=edge[x].size();
for(int i=;i<Size;i++)
if(number[edge[x][i]]==)
{
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[*N+]={};
void updata(int x,int v)
{
for(int i=x;i<*N;i+=i&(-i))c[i]+=v;
} int Sum(int x)
{
int ans=;
while(x>)
{
ans+=c[x];
x-=x&(-x);
}
return ans;
} int main()
{
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int p;
scanf("%d",&p);
edge[i].push_back(p);
edge[p].push_back(i);
} for(int i=;i<=n;i++)scanf("%d",&w[i]); dfs(); for(int i=;i<=n;i++)
{
interval.push_back((ss){number[i],number[i]+children[i]-,i,});
interval.push_back((ss){number[i]+children[i],n+number[i]-,i,});
}
for(int i=;i<=n;i++)
{
dfsorder[i]=w[dfsorder[i]];
dfsorder[n+i]=dfsorder[i];
}
sort(interval.begin(),interval.end()); int last[N]={};
int c1=; for(int i=;i<*n;i++)
{
if(interval[i].l>interval[i].r)continue; for(int j=c1;j<=interval[i].r;j++)
{
if(last[dfsorder[j]]==)
{
updata(j,);
last[dfsorder[j]]=j;
}
else
{
updata(last[dfsorder[j]],-);
updata(j,);
last[dfsorder[j]]=j;
}
}
interval[i].ans=Sum(interval[i].r)-Sum(interval[i].l-);
c1=interval[i].r+;
} int sum[N]={},ans=; for(int i=;i<*n;i++)
{
sum[interval[i].index]+=interval[i].ans;
ans=max(ans,sum[interval[i].index]);
} printf("%d\n",ans);
return ;
}

Split The Tree的更多相关文章

  1. [Split The Tree][dfs序+树状数组求区间数的种数]

    Split The Tree 时间限制: 1 Sec  内存限制: 128 MB提交: 46  解决: 11[提交] [状态] [讨论版] [命题人:admin] 题目描述 You are given ...

  2. [CodeForces1059E] Split the Tree

    树形DP. 用倍增处理出来每个点往上能延伸出去的最远路径,nlogn 对于每个节点,如果它能被后代使用过的点覆盖,就直接覆盖,这个点就不使用,否则就ans++,让传的Max改成dp[x] #inclu ...

  3. HDU6504 Problem E. Split The Tree【dsu on tree】

    Problem E. Split The Tree Problem Description You are given a tree with n vertices, numbered from 1 ...

  4. Codeforces Round #514 (Div. 2) E. Split the Tree(倍增+贪心)

    https://codeforces.com/contest/1059/problem/E 题意 给出一棵树,每个点都有一个权值,要求你找出最少条链,保证每个点都属于一条链,而且每条链不超过L个点 和 ...

  5. [CF1059E]Split the Tree[贪心+树上倍增]

    题意 给定 \(n\) 个节点的树,点有点权 \(w\) ,划分成多条儿子到祖先的链,要求每条链点数不超过 \(L\) ,和不超过 \(S\),求最少划分成几条链. \(n\leq 10^5\) . ...

  6. Codeforces 1059E. Split the Tree

    题目:http://codeforces.com/problemset/problem/1059/E 用倍增可以在nlog内求出每个节点占用一个sequence 时最远可以向父节点延伸到的节点,对每个 ...

  7. CF1059E Split the Tree(倍增)

    题意翻译 现有n个点组成一棵以1为根的有根树,第i个点的点权为wi,需将其分成若干条垂直路径使得每一个点当且仅当被一条垂直路径覆盖,同时,每条垂直路径长度不能超过L,点权和不能超过S,求最少需要几条垂 ...

  8. Codeforces 461B. Appleman and Tree[树形DP 方案数]

    B. Appleman and Tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. CF461B Appleman and Tree (树DP)

    CF462D Codeforces Round #263 (Div. 2) D Codeforces Round #263 (Div. 1) B B. Appleman and Tree time l ...

随机推荐

  1. SAP产品的Field Extensibility

    SAP开发人员的工作职责,除了实现软件的功能性需求外,还会花费相当的精力实现一些非功能性需求,来满足所谓的SAP Product Standard(产品标准).这些产品标准,包含在SAP项目实施中大显 ...

  2. 系统相册中获取gif图片 保证取到的图片不会改变

    NSURL *imageRefURL = [info valueForKey:UIImagePickerControllerReferenceURL];                         ...

  3. 4个Linux服务器监控工具

    下面是我想呈现给你的4个强大的监控工具. htop – 交互式进程查看器 你可能知道在机器上查看实时进程的标准工具top.如果不知道,请运行$ top看看,运行$ man top阅读帮助手册. hto ...

  4. vue 中 $set 的使用

    在我们使用vue进行开发的过程中,可能会遇到一种情况:当生成vue实例后,当再次给数据赋值时,有时候并不会自动更新到视图上去: <!DOCTYPE html> <html> & ...

  5. 【转】Spring, MyBatis 多数据源的配置和管理

    同一个项目有时会涉及到多个数据库,也就是多数据源.多数据源又可以分为两种情况: 1)两个或多个数据库没有相关性,各自独立,其实这种可以作为两个项目来开发.比如在游戏开发中一个数据库是平台数据库,其它还 ...

  6. 第2节 azkaban调度:16、azkaban的介绍以及azkaban的soloserver的安装使用

    2. 工作流调度器azkaban 2.1 概述 azkaban官网: https://azkaban.github.io/ 2.1.1为什么需要工作流调度系统 l  一个完整的数据分析系统通常都是由大 ...

  7. StringMVCWeb接受前台值的几种方式

    这些决定与request   header   的Content-Type属性 1.通过@RequestParam @RequestParam Map<String, Object> pa ...

  8. 009 CSS选择器

    CSS选择器 一.基础选择器 1.通配选择器 * { border: solid; } 匹配文档中所有标签:通常指html.body及body中所有显示类的标签 2.标签选择器 div { backg ...

  9. Go统计键盘输入随机字母的个数

    package main import "fmt" //通过键盘输入20个小写字母,统计个数 func main(){ //通过键盘器获取字符 var arr [20]byte f ...

  10. vue-music:歌词的其他功能

    由于歌词的播放需要歌曲播放,切换歌曲,歌曲的播放模式等等有关联,因此,需要在这几处处理相关问题 1.循环播放回不到开始位置 loop() { this.$refs.audio.currentTime ...