两个子任务真的是坑……考试的时候想到了60分的算法,然而只拿到了20分(各种沙雕错,没救了……)。

算法1:

对于测试点1,直接n遍dfs即可求出答案,复杂度O(n^2),然而还是有好多同学跑LCA/最短路……

期望得分10;

算法2(搬运题解,因为这个我没有想到……):

t=1的数据最直接的想法是枚举所有可能的a[]数组判断是否可行.第2个测试点n<=5,1<=a[i]<=20.注意20^5=3200000,直接暴力搜索a[i]的取值是可以承受的,可以通过第2个测试点,期望得分10分,结合算法1,期望得分20分.

算法3:

对于测试点6,7。我们可以发现每个点的dis都有联系,这不就是二次扫描与换根吗(具体看代码理解)。结合算法2期望得分40;

 void dfs2(int x,int fa)
{
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
b[v(i)]=b[x];
b[v(i)]-=sum[v(i)];
b[v(i)]+=sum[x]-sum[v(i)];
sum[x]-=sum[v(i)];
sum[v(i)]+=sum[x];
dfs2(v(i),x);
sum[v(i)]-=sum[x];
sum[x]+=sum[v(i)];
}
}

第二次扫描的代码

算法4:

t=1的数据中,b数组的表达式写出来之后,每个b[i]对应一个关于a[i]和树上两点距离的方程,例如b[1]=dis(1,1)*a[1]+dis(1,2)*a[2]+dis(1,3)*a[3]+...+dis(1,n)*a[n],于是可以列出n个方程用高斯消元求解,可以通过第2,3,4个测试点,期望得分30分,结合算法3,期望得分60分。要注意的一点是,高斯消元中要注意这句话‘if(fabs(sa[j][i])>fabs(sa[i][i]))’,本人死于此……还有不少人死于强制类型转化的四舍五入,其实printf("%0.0lf")即可;

之后的算法题解写的已经很清晰了,我觉得我也写不了这么清楚,就直接搬运了。

算法5:

对于测试点5,树退化为1条链。这个测试点的作用主要在于启发选手想到正解的思路(然而我并没有什么启发……)。

t=0时,我们分别考虑编号小于i和大于i的点对b[i]的贡献.那么离得越远的点对答案的贡献越大.分别考虑每条边对答案的贡献,那么左侧的某条边对答案的贡献就是这条边左侧全部a[i]之和.实际上,我们对a[i]分别求取两次前缀和,两次后缀和即可完成对b[i]的计算.

记suf(i)为a[i]+a[i+1]+....+a[n-1]+a[n],pre(i)为a[1]+a[2]+...+a[i-1]+a[i],则b[i]=pre(1)+pre(2)+...+pre(i-1)+suf(i+1)+suf(i+2)+...+suf(n-1)+suf(n)

考虑t=1的情况.

我们知道suf(2)+suf(3)+...+suf(n)的值(即b[1]),知道pre(1) + suf(3) + suf(4) +...+suf(n)的值(即b[2]),知道pre(1)+pre(2)+suf(4)+...+suf(n)的值(即b[3]),注意到这些式子有很多项是一样的,考虑作差.可以得到下面的式子:

b[2]-b[1]=pre(1)-suf(2),b[3]-b[2]=pre(2)-suf(3).....b[i+1]-b[i]=pre(i)-suf(i+1)

这些式子是有实际意义的,考虑从b[1]变到b[2]时答案的变化量,变化的就是1和2之间连边的贡献.

同时,记SUM=a[1]+a[2]+...+a[n-1]+a[n],显然pre(i)+suf(i+1)=SUM,因此pre(i)=SUM-suf(i+1),将上面式子中所有pre换成suf,我们就知道了

SUM-2*suf(2) ,SUM-2*suf(3)...SUM-2*suf(n)的取值。

注意我们将n个式子作差之后得到了n-1个等式,实际上是丢弃了一些信息,只保留了b[i]之间的相对大小而忽略了b[i]自身的数值大小.于是考虑b[1]=suf(2)+suf(3)+suf(4)+... +suf(n),我们发现suf(2)到suf(n)都恰好出现了一次,而之前得到了n-1个形如SUM-2*suf(i)的式子,将这n-1个式子相加,suf(2),suf(3)...suf(n)前面的系数都是2,SUM的系数为(n-1),那么把这个式子加上2*b[1],就得到了(n-1)*SUM,将求得的SUM代入之前的n-1个式子可以得到suf(2),suf(3),suf(4)......suf(n),差分一下即可得到a数组.

时间复杂度O(n),可以通过第5个测试点.推出这个做法,树上的做法也就不难想了.

算法6(满分算法):

考虑树上的问题.

t=0的时候,我们可以先暴力计算出b[1],然后从b[1]出发开始dfs,由某个点的父亲的b[i]推出这个点的b[i],变化的是这个点和父亲的连边的贡献,也就是这条边两侧的点的a[i]之和的差值.

t=1的时候,顺着链上的思路,我们先随便找一个点为根建树,将有边直接相连的两个点的b[i]作差.设x的父亲为prt[x],以x为根的子树中所有a[i]之和为sum(x), SUM=a[1]+a[2]+...+a[n-1]+a[n],那么b[x]-b[prt[x]]=(SUM-sum(x))-sum(x).

同链的情况一样,得到n-1个式子,将树根的b[i]也列出式子,可以求出全部a[i]之和,然后就可以根据之前的式子推出所有的a[i],和链的做法类似,不再赘述.

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define MAXN 100010
#define int LL
#define LL long long
#define esp 1e-8
#define ma(x) memset(x,0,sizeof(x))
using namespace std;
struct edge
{
int u,v,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define n(x) ed[x].nxt
}ed[MAXN*];
int first[MAXN],num_e;
#define f(x) first[x]
int T,n,t;
LL a[MAXN],b[MAXN];
LL dis[MAXN],sum[MAXN];
LL SUM,suf[MAXN];
LL SUM_2suf[MAXN];
LL SUM_2sum[MAXN];
LL TSUM=; int map[][];
double sa[][],sb[];
void GS()
{
for(int i=;i<=n;i++)
{
for(int j=i;j<=n;j++)
if(fabs(sa[j][i])>fabs(sa[i][i]))
{
for(int k=;k<=n;k++)
swap(sa[i][k],sa[j][k]);
swap(sb[i],sb[j]);
}
for(int j=;j<=n;j++)
{
if(j==i)continue;
if(fabs(sa[i][i])<=esp)continue;
double cal=sa[j][i]/sa[i][i];
for(int k=;k<=n;k++)
sa[j][k]-=sa[i][k]*cal;
sb[j]-=sb[i]*cal;
}
}
}
void dfs(int x,int fa)
{
sum[x]=a[x];
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
dis[v(i)]=dis[x]+;
dfs(v(i),x);
sum[x]+=sum[v(i)];
}
}
void dfs2(int x,int fa)
{
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
b[v(i)]=b[x];
b[v(i)]-=sum[v(i)];
b[v(i)]+=sum[x]-sum[v(i)];
sum[x]-=sum[v(i)];
sum[v(i)]+=sum[x];
dfs2(v(i),x);
sum[v(i)]-=sum[x];
sum[x]+=sum[v(i)];
}
}
void dfs3(int x,int fa)
{
if(x!=)SUM_2sum[x]=b[x]-b[fa];
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
dfs3(v(i),x);
}
void dfs4(int x,int fa)
{
if(x==)sum[x]=SUM;
else sum[x]=(SUM-SUM_2sum[x])/;
a[x]=sum[x];
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
dfs4(v(i),x);
a[x]-=sum[v(i)];
}
}
inline int read();
inline void add(int u,int v);
signed main()
{
// freopen("in.txt","r",stdin); T=read();
while(T--)
{
ma(sum);ma(first);num_e=;ma(dis);ma(a);ma(b);
ma(map);ma(sa);ma(sb);ma(suf);SUM=;ma(SUM_2suf);
ma(SUM_2sum);TSUM=;
bool pd=;
n=read();int u,v;
for(int i=;i<n;i++)
{
u=read(),v=read();
if(v!=u+)pd=;
add(u,v),add(v,u);
}
t=read();
if(t==)
{
for(int i=;i<=n;i++)a[i]=read();
if(n<=)
{
for(int i=;i<=n;i++)
{
dis[i]=;
dfs(i,);
for(int j=;j<=n;j++)b[i]+=a[j]*dis[j];
}
for(int i=;i<=n;i++)
printf("%lld ",b[i]);
puts("");
continue;
}
else
{
dis[]=;dfs(,);
for(int i=;i<=n;i++)b[]+=dis[i]*a[i];
dfs2(,);
for(int i=;i<=n;i++)
printf("%lld ",b[i]);
puts("");
continue;
}
}
if(t==)
{
for(int i=;i<=n;i++)b[i]=read();
if(n<=)
{
for(int i=;i<=n;i++)
{
dis[i]=;dfs(i,);
for(int j=;j<=n;j++)map[i][j]=dis[j];
}
for(int i=;i<=n;i++)sb[i]=b[i];
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)sa[i][j]=map[j][i];
GS();
for(int i=;i<=n;i++)
printf("%0.0lf ",sb[i]/sa[i][i]);
puts("");
continue;
}
if(pd)
{
for(int i=;i<=n;i++)SUM_2suf[i]=b[i]-b[i-];
LL tem=;
for(int i=;i<=n;i++)tem+=SUM_2suf[i];
tem+=b[]*;
SUM=tem/(n-);
for(int i=;i<=n;i++)suf[i]=(SUM-SUM_2suf[i])/;
suf[]=SUM;suf[n+]=;
for(int i=;i<=n;i++)a[i]=suf[i]-suf[i+];
for(int i=;i<=n;i++)
printf("%lld ",a[i]);
puts("");
continue;
}
else
{
dfs3(,);
for(int i=;i<=n;i++)TSUM+=SUM_2sum[i];
TSUM+=b[]*;
SUM=TSUM/(n-);
dfs4(,);
for(int i=;i<=n;i++)
printf("%lld ",a[i]);
puts("");
continue;
}
}
}
}
inline int read()
{
int s=;char a=getchar();
while(a<''||a>'')a=getchar();
while(a>=''&&a<=''){s=s*+a-'';a=getchar();}
return s;
}
inline void add(int u,int v)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
n(num_e)=f(u);
f(u)=num_e;
}

HZOJ 单的更多相关文章

  1. HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)

    考试T2,考试时想到了40pts解法,即对于求b数组,随便瞎搞一下就oxxk,求a的话,很明显的高斯消元,但考试时不会打+没开double挂成10pts(我真sb),感觉考试策略还是不够成熟,而且感觉 ...

  2. H5单页面手势滑屏切换原理

    H5单页面手势滑屏切换是采用HTML5 触摸事件(Touch) 和 CSS3动画(Transform,Transition)来实现的,效果图如下所示,本文简单说一下其实现原理和主要思路. 1.实现原理 ...

  3. 快速构建H5单页面切换骨架

    在Web App和Hybrid App横行的时代,为了拥有更好的用户体验,单页面应用顺势而生,单页面应用简称`SPA`,即Single Page Application,就是只有一个HTML页面的应用 ...

  4. ASP.NET Aries 入门开发教程9:业务表单的开发

    前言: 经过前面那么多篇的列表的介绍,终于到了大伙期待的表单开发了. 也是本系列的最后一篇文章了! 1:表单页面的权限设置与继承 对于表单页面,权限的设置有两种: 1:你可以选择添加菜单(设置为不显示 ...

  5. 【CSS进阶】伪元素的妙用--单标签之美

    最近在研读 <CSS SECRET>(CSS揭秘)这本大作,对 CSS 有了更深层次的理解,折腾了下面这个项目: CSS3奇思妙想 -- Demo (请用 Chrome 浏览器打开,非常值 ...

  6. bootstrap + requireJS+ director+ knockout + web API = 一个时髦的单页程序

    也许单页程序(Single Page Application)并不是什么时髦的玩意,像Gmail在很早之前就已经在使用这种模式.通常的说法是它通过避免页面刷新大大提高了网站的响应性,像操作桌面应用程序 ...

  7. 探索ASP.NET MVC5系列之~~~3.视图篇(下)---包含常用表单和暴力解猜防御

    其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.ht ...

  8. SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=》提升)

     SignalR快速入门 ~ 仿QQ即时聊天,消息推送,单聊,群聊,多群公聊(基础=>提升,5个Demo贯彻全篇,感兴趣的玩才是真的学) 官方demo:http://www.asp.net/si ...

  9. jQuery学习之路(8)- 表单验证插件-Validation

    ▓▓▓▓▓▓ 大致介绍 jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求.该插件捆绑了一套有用的验证方法,包括 ...

随机推荐

  1. 剖析Unreal Engine超真实人类的渲染技术Part 1 - 概述和皮肤渲染

    一.概述 1.1 数字人类的概要 数字人类(Digital Human)是利用计算机模拟真实人类的一种综合性的渲染技术.也被称为虚拟人类.超真实人类.照片级人类. 它是一种技术和艺术相结合的综合性模拟 ...

  2. 反向代理在APP通过无线路由接入3G/4G时的特殊作用

    由于某些需求,要临时搭建局域网络,给小范围内大量移动客户端提供特定的网络服务,这样的服务通常包含常见的HTTP服务.数据文件下载服务.RESTFul接口服务等.市面常见的非企业级WIFI路由器能够承受 ...

  3. Spring Boot2(三):使用Spring Boot2集成Redis缓存

    前言 前面一节总结了SpringBoot实现Mybatis的缓存机制,但是实际项目中很少用到Mybatis的二级缓存机制,反而用到比较多的是第三方缓存Redis. Redis是一个使用ANSI C编写 ...

  4. python文件及路径管理函数

    glob模块 说明: 1.glob是python自己带的一个文件操作相关模块,用它可以查找符合自己目的的文件,就类似于Windows下的文件搜索, 支持通配符操作 *.?.[] 这三个通配符,*代表0 ...

  5. Qemu搭建ARM vexpress开发环境(三)----NFS网络根文件系统

    Qemu搭建ARM vexpress开发环境(三)----NFS网络根文件系统 标签(空格分隔): Qemu ARM Linux 经过上一篇<Qemu搭建ARM vexpress开发环境(二)- ...

  6. Confluence安装、汉化及jira整合

    今天上午装了一下Confluence,刚开始装的时候成功了,成功后进入数据库配置阶段,本人想把jira和confluence整合一起用,刚开始提示数据库连接问题,后来一直问题提示Connection ...

  7. 智能小程序关于Filter过滤器的简单使用

    <filter module="swan"> export default { imgurl: (imgUrl) => { var imgurlprefix = ...

  8. Scala 学习之路(三)—— 流程控制语句

    一.条件表达式if Scala中的if/else语法结构与Java中的一样,唯一不同的是,Scala中的if表达式是有返回值的. object ScalaApp extends App { val x ...

  9. Spark学习之路(一)—— Spark简介

    一.简介 Spark于2009年诞生于加州大学伯克利分校AMPLab,2013年被捐赠给Apache软件基金会,2014年2月成为Apache的顶级项目.相对于MapReduce的批处理计算,Spar ...

  10. spring boot 2.x 系列 —— spring boot 整合 dubbo

    文章目录 一. 项目结构说明 二.关键依赖 三.公共模块(boot-dubbo-common) 四. 服务提供者(boot-dubbo-provider) 4.1 提供方配置 4.2 使用注解@Ser ...