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. python_112_断言

    #断言 如果满足断言的执行程序,如果不满足则抛错误 assert type(1) is int print('断言正确的话,就继续执行') # assert type('a') is int #Ass ...

  2. 二、pandas入门

    import numpy as np import pandas as pd Series: #创建Series方法1 s1=pd.Series([1,2,3,4]) s1 # 0 1 # 1 2 # ...

  3. monkeyrunner之控件ID不存在或重复(转载lynnLi)

    我们在用monkeyrunner进行Android自动化时,通过获取坐标点或控件ID进行一系列操作.由于使用坐标点时,屏幕分辨率一旦更改,则代码中用到坐标的地方都要修改,这样导致代码的复用率较低.因此 ...

  4. syslog(),closelog()与openlog()--日志操作函数 (2)

    文章出处:http://blog.chinaunix.net/uid-26583794-id-3166083.html 守护进程日志的实现 syslogd守护进程用于解决守护进程的日志记录问题,而日志 ...

  5. ios之键盘的自定义

    一.键盘通知 当文本View(如UITextField,UITextView,UIWebView内的输入框)进入编辑模式成为first responder时,系统会自动显示键盘.成为firstresp ...

  6. GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 (线段树)

    GSS4 - Can you answer these queries IV || luogu4145上帝造题的七分钟2 / 花神游历各国 GSS4 - Can you answer these qu ...

  7. easyUI之datagrid绑定后端返回数据的两种方式

    先来看一下某一位大佬留下的easyUI的API对datagrid绑定数据的两种方式的介绍. 虽然精简,但是,很具有“师傅领进门,修行靠个人”的精神,先发自内心的赞一个. 但是,很多人和小编一样,第一次 ...

  8. 小型LAMP搭建

    一.dns的搭建 安装dns服务 yum install bind 修改dns的主配置文件 [root@234c17 named]# vim /etc/named.conf // // named.c ...

  9. css3的border-radius属性使用方法

    1.border-radius可以包含两个参数值,第一个水平圆角半径,第二个为垂直半径,并且两个参数值用“/”分开. 2.border-radius:设置一个值为四个角都相同,两个值为左上和右下相同, ...

  10. js 类型之间的相互转化

    设置元素对象属性 var img = document.querySelector("img") img.setAttribute("src","ht ...