题目传送门(内部题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. O057、Delete Volume 操作

    参考https://www.cnblogs.com/CloudMan6/p/5648665.html   状态为Available 的volume 才能够被delete,如果volume当前已经被at ...

  2. 转:GitHub团队项目合作流程

    转自:https://www.cnblogs.com/schaepher/p/4933873.html GitHub团队项目合作流程   已在另一篇博客中写出关于以下问题的解决,点此进入: 同步团队项 ...

  3. HTML的学习(注释)

    <!--charset 编码字符集--> <!--UTF-8 万国码 gb2312 中国标准第2312条 中文,韩文....大部分的亚裔语言(繁体字不支持) GBK 在上面的基础之上 ...

  4. Javascript 中apply call bind

    在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. 先来一个例子: functi ...

  5. 编译原理-递归下降分析法 c程序部分的分析

    实验三 语法分析程序实验 专业 商软2班   姓名 黄仲浩  学号 201506110166 一. 实验目的      编制一个部分文法分析程序. 二. 实验内容和要求 输入:源程序字符串 输出:正确 ...

  6. count(*),count(1),count(字段)

    如果null参与聚集运算,则除count(*)之外其它聚集函数都忽略null. 如:    ID     DD     1      e     2    null    select  count( ...

  7. 阿里云linux配置ftp服务

    阿里云linux配置ftp服务 一.ftp服务安装 运行以下命令安装ftp yum install -y vsftpd 运行以下命令打开及查看etc/vsftpd cd /etc/vsftpd ls ...

  8. python 匿名函数lambda使用

    lambda函数语法格式: lambda函数 后面参数可以有一个或多个,冒号后面是python表达式: lambda 参数1,参数2,参数3...:表达式 # 一个参数情况: a = lambda x ...

  9. MySQL添加唯一索引

    1 语法如下 ALTER TABLE `t_user` ADD unique(`username`);

  10. FASTCGI/CGI

    在了解这两个协议之前,我们先谈一下动态网页 动态网页 是指跟静态网页相对的一种网页编程技术.静态网页,随着html代码的生成,页面的内容和显示效果就基本上不会发生变化了--除非你修改页面代码.而动态网 ...