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. 如何诊断 11.2 集群节点驱逐问题 (文档 ID 1674872.1)

    适用于: Oracle Database - Enterprise Edition - 版本 11.2.0.1 到 11.2.0.2 [发行版 11.2]本文档所含信息适用于所有平台 用途 这篇文档提 ...

  2. 提取循环中包含continue的语句封装成方法

    demo如下: private void button1_Click(object sender, EventArgs e) { ;i<;i++) { if (!a(i)) { continue ...

  3. Ubuntu 18.04 上使用 OpenJDK 安装并运行 Tomcat

    在Linux上安装与卸载JDK和JRE,两种常用方法: 一.通过 apt-get 命令在线进行安装与卸载(会自动配置好环境变量) 二.通过下载并解压 .tar.gz 包进行手动安装与手动卸载(需要手动 ...

  4. 拼凑json的实例

    一,拼凑  json 串 并传到后台 function writeToJson(num){ var i = 1; var jsonData = "["; for(i=1;i< ...

  5. (1)JSTL的13个core标签库

     标准标签库JSTL的全名为:Java Server Pages Standard Tag Library. (jsp  standard tag library) JSTL主要提供了5大类标签库: ...

  6. MySQL插入SQL语句后在phpmyadmin中注释显示乱码

    自己写一个建一个简单的数据表,中间加了个注释,但是用PHPmyadmin打开后发现注释不对. 就先查询了一下sql 语句 发现SQL 语句并没有问题,感觉像是显示编码的问题,就先用set names ...

  7. ios 点餐系统

    这个程序的主要界面就是一个TabBarController.总共三个标签,第一个是所有的可点的菜,第二个是已点的菜,第三个是可以留言或者查看所有留言. 下面是第一个页面: 右上角的i按钮是添加新菜,每 ...

  8. ios之UIImageView

    UIImageView,顾名思义,是用来放置图片的.使用Interface Builder设计界面时,当然可以直接将控件拖进去并设置相关属性,这就不说了,这里讲的是用代码. 1.创建一个UIImage ...

  9. 大数据学习系列之Hadoop、Spark学习线路(想入门大数据的童鞋,强烈推荐!)

    申明:本文出自:http://www.cnblogs.com/zlslch/p/5448857.html(该博客干货较多) 1 Java基础: 视频方面:          推荐<毕向东JAVA ...

  10. Ubuntu创建应用快捷方式

    Ubuntu创建应用快捷方式 新建一个.desktop文件 vi eclipse.desktop 然后又进行编辑 [Desktop Entry] Encoding=UTF-8 Name=eclipse ...