题目传送门(内部题103)


输入格式

  第一行一个数$n$,表示结点的个数。
  第二行$n–1$个数,第$i$个数是$p[i+1]$。$p[i]$表示结点$i$的父亲是$p[i]$。数据保证$p[i]<i$。
  第三行$n$个数,$a[1],a[2],...,a[n]$,表示关卡表。数据保证这是一个排列。
  第四行$n$个数,$x[1],x[2],...,x[n]$,表示结点的权值。


输出格式

  输出一个数表示答案。即对于所有可能的回合,你们能获得的总收益是多少。


数据范围与提示

  对于$20\%$的数据,满足$n\leqslant 100$。
  对于$40\%$的数据,满足$n\leqslant 2,000$。
  对于$60\%$的数据,满足$n\leqslant 50,000$。
  对于另外$20\%$的数据,排列$a[i]$是用如下的算法生成的:从一号点开始对树做$dfs$,到达一个节点的时候输出这个结点。
  对于$100\%$的数据,满足$1\leqslant n\leqslant 200,000,0\leqslant x[i]\leqslant 100,000,p[i]<i$,$a[i]$是一个排列。


题解

其实另外$20\%$的数据就是正解的一个引导。

显然对于这个部分分无非就是输出每一个点的子节点的$size$相互之间的乘积和乘上这个点的$x$值即可。

那么考虑正解。

用$dsu\ on\ tree$思想,每个节点继承儿子中最重的节点的信息,其他儿子暴力合并;用两个数组记录当前位置是否是一个极长区间的左(右)端点并记录另一个端点的位置,加入一个节点时尝试合并左右信息并统计合并后的方案数即可。

时间复杂度:$\Theta(n\log n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
struct rec{int nxt,to;}e[200000];
int head[200001],cnt;
int n;
int a[200001],val[200001],size[200001],son[200001],l[200001],r[200001],vis[200001],dfn[200001],now;
long long ans;
void add(int x,int y)
{
e[++cnt].nxt=head[x];
e[cnt].to=y;
head[x]=cnt;
}
void dfs(int x)
{
size[x]=1;
for(int i=head[x];i;i=e[i].nxt)
{
dfs(e[i].to);
size[x]+=size[e[i].to];
if(size[son[x]]<size[e[i].to])son[x]=e[i].to;
}
}
long long insert(int x)
{
vis[a[x]]=now;
if(vis[a[x]+1]!=now)l[a[x]+1]=r[a[x]+1]=0;
if(vis[a[x]-1]!=now)l[a[x]-1]=r[a[x]-1]=0;
long long L=l[a[x]-1],R=r[a[x]+1],len=l[a[x]-1]+r[a[x]+1]+1;
l[a[x]]=L+1;r[a[x]]=R+1;l[a[x]+R]=r[a[x]-L]=len;
return len*(len+1)/2-L*(L+1)/2-R*(R+1)/2;
}
long long ask(int x)
{
long long res=insert(x);
for(int i=head[x];i;i=e[i].nxt)
res+=ask(e[i].to);
return res;
}
int dfs(int x,int opt)
{
now=dfn[x]=x;
long long res=0,num=0,flag=0;
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=son[x])res-=dfs(e[i].to,0);
if(son[x])
{
flag=dfs(son[x],1);
num+=flag;
now=dfn[x]=dfn[son[x]];
}
num+=insert(x);
for(int i=head[x];i;i=e[i].nxt)
if(e[i].to!=son[x])num+=ask(e[i].to);
ans+=(res+num-flag)*val[x];
return num;
}
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;i++){int x;scanf("%d",&x);add(x,i);}
for(int i=1;i<=n;i++){int x;scanf("%d",&x);a[x]=i;}
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
dfs(1);
dfs(1,1);
printf("%lld",ans);
return 0;
}

rp++

[CSP-S模拟测试]:射手座之日(dsu on tree)的更多相关文章

  1. 联赛模拟测试10 C. 射手座之日

    题目描述 分析 方法一(线段树) 线段树维护的是以当前节点为左端点的区间的贡献 而区间的右端点则会从 \(1\) 到 \(n\) 逐渐右移 当我们把右端点从 \(i-1\) 的位置扩展到 \(i\) ...

  2. csp-s模拟测试94

    csp-s模拟测试94 一场简单题,打爆了.$T1$脑抽分解质因数准备分子分母消,想了半天发现$jb$互质直接上天,果断码了高精滚蛋.$T2$无脑手玩大样例,突然灵光一闪想到映射到前$K$大小的区间, ...

  3. [考试反思]1030csp-s模拟测试94:未知

    排名也未知.第1或第5. 分数也未知,300或260. 人生真是大起大落... 啊啊啊啊啊我好感动啊竟然重测了一次----- 评测机怎么测怎么RE,本机怎么测怎么AC(任意编译指令,任意评测平台) 结 ...

  4. [CSP-S模拟测试94]题解

    A.凉宫春日的忧郁 高精硬上似乎跑不过,其实可以都取个$log$.那么只需要比较$y\times log ^x$和$\sum \limits _{i=1}^y log^i$就好了. #include& ...

  5. Android单元测试与模拟测试详解

    测试与基本规范 为什么需要测试? 为了稳定性,能够明确的了解是否正确的完成开发. 更加易于维护,能够在修改代码后保证功能不被破坏. 集成一些工具,规范开发规范,使得代码更加稳定( 如通过 phabri ...

  6. [开源]微信在线信息模拟测试工具(基于Senparc.Weixin.MP开发)

    目前为止似乎还没有看到过Web版的普通消息测试工具(除了官方针对高级接口的),现有的一些桌面版的几个测试工具也都是使用XML直接请求,非常不友好,我们来尝试做一个“面向对象”操作的测试工具. 测试工具 ...

  7. 安装nginx python uwsgi环境 以及模拟测试

    uwsgi帮助文档: http://uwsgi-docs-cn.readthedocs.io/zh_CN/latest/WSGIquickstart.html http://uwsgi-docs.re ...

  8. 利用Python中的mock库对Python代码进行模拟测试

    这篇文章主要介绍了利用Python中的mock库对Python代码进行模拟测试,mock库自从Python3.3依赖成为了Python的内置库,本文也等于介绍了该库的用法,需要的朋友可以参考下     ...

  9. 转 C#实现PID控制的模拟测试和曲线绘图

    C#实现PID控制的模拟测试和曲线绘图   本文分两部分,一部分是讲PID算法的实现,另一部分是讲如何用动态的曲线绘制出PID运算的结果. 首先,PID算法的理论模型请参考自动控制理论,最早出现的是模 ...

随机推荐

  1. js循环遍历性能

    定length for循环 (有length) 不定length for循环(使用数组length) 不定length for循环(判断数组length是否存在) forEach(Array自带,对某 ...

  2. luogu题解P2502[HAOI2006]旅行--最小生成树变式

    题目链接 https://www.luogu.org/problemnew/show/P2502 分析 一个很\(naive\)的做法是从\(s\)到\(t\)双向BFS这当然会TLE 这时我就有个想 ...

  3. shiro权限控制配置

    shiro配置流程 web.xml中配置shiro的filter spring中配置shiro的过滤器工厂,指定对不同地址权限控制 , 传入安全管理器 配置安全管理器,传入realm,realm中定义 ...

  4. Spring MVC之@RequestParam @RequestBody @RequestHeader 等详

    Spring MVC之@RequestParam @RequestBody @RequestHeader 等详     引言: 接上一篇文章,对@RequestMapping进行地址映射讲解之后,该篇 ...

  5. vue2.0+按需引入element-ui报错

    项目使用vue脚手架自动生成的,vue版本为^2.5.16.项目中需要按需使用element-ui,根据element-ui的官方文档,一开始在babel.config.js文件中修改配置 modul ...

  6. JVM类加载机制和内存模型

    一.JVM类加载机制 首先需要了解一下类加载器(ClassLoader): ClassLoader是Java的一个核心组件,它主要作用是从系统外部获得Class二进制数据流,然后将数据流装载到系统,交 ...

  7. 分布式之协调服务Zookeeper专题第一讲

    写在前面: 再谈架构演进: 1.单体架构->tomcat(war) 演进:水平拆分(服务拆分,(用户服务,订单服务,商品服务)) 涉及问题:1).服务通信(webservice) 2).三态问题 ...

  8. Linux使用wget仿站

    运行命令 $ wget -r -p -np -k www.avatrade.cn 参数说明 -r --recursive(递归) specify recursive download.(指定递归下载) ...

  9. 数据驱动——ddt

    1: pip3 install ddt 2: @ddt 装饰 @data((2,3),(4,5)) 支持列表,元祖,字典 @unpack 解压数据   1 import unittest 2 from ...

  10. PAT乙级1018

    题目链接 https://pintia.cn/problem-sets/994805260223102976/problems/994805304020025344 题解 刚开始做很懵逼,可能并不难吧 ...