HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)
考试T2,考试时想到了40pts解法,即对于求b数组,随便瞎搞一下就oxxk,求a的话,很明显的高斯消元,但考试时不会打+没开double挂成10pts(我真sb),感觉考试策略还是不够成熟,而且感觉考试时间很不够用,一直在瞎yy+code,听讲题DeepinC 12min就打出了T150pts,这不仅是思维上的劣势,而且打代码的速度必须要加上来啊,不然就算有好想法也打不出来(也没啥好想法)。
接下来就是正经八本的题解了:
首先我们可以来一波玄学复杂度分析,数据范围1e5,要么$O(nlogn)$,要么$O(n)$,这是树上的问题,$O(nlogn)$的算法其实不多也就lca和乱七八糟的数据结构,但和这题显然不搭,所以我们尽量做到$O(n)$的复杂度。
首先来考虑给a求b,这是比较简单的一问,其实有点像树上dp,就是从父节点转移到子节点,首先我们可以$O(n)$求出不$b[1]$,然后就是开始考虑怎么转移,其实思考方式有点像「HAOI 2015」树上染色这题的思路都是考虑边对答案的影响,在回来看这题,如果从父节点转移到子节点那么,子节点子树外的点距离都加1,那么每个点的贡献都加了一个点权,但是子节点子树内的点却恰好相反,那么我们设$sum[i]$为以$i$为根的子树的点权和,那么用式子把我们刚才的分析表示出来就是$b[y]=b[x]+sum[1]-sum[y]-sum[y]=b[x]+sum[1]-2*sum[y]$,那么第一个问题就很好的在$O(n)$复杂度内得到了解决。
在来考虑给b求a,这是比较困难的一问,似乎除了高斯消元我们想不出更好的算法,那就只能硬着头皮推式子,这题好就好在转化很多,而且不能放过任何一个你已经推出来的式子,我们观察到上一问推出来的式子是和b数组有直接关系的,那么我们移项,得到$b[y]-b[x]=sum[1]-2*sum[y]$,这样就相当与把a,b数组建立了关系,其实这是很重要的思想,所有的题不都是给你已知量求未知量么?接着看题,我们设$dt[y]=b[y]-b[x]=sum[1]-2*sum[y]$,为什么要这么设呢,首先我们来证一个结论$b[1]=\Sigma_{i=2}^n{sum[i]}$,看上去很显然?蒟蒻博主并不这么觉得,我们来证一下不b[1]是什么,就是每个点的深度乘以每个点的点权,我们在来看右边的式子是所有sum[i]之和,那么每个点对右边式子的贡献就是点权乘上他有多少代祖宗,那这不就是深度吗,所以两边是相等的,证毕。
然后我们设$tot=\Sigma_{i=2}^n{dt[i]}=(n-1)sum[1]-2*\Sigma_{i=2}^n{sum[i]}=(n-1)sum[1]-2*b[1]$
这样我们就可以求出sum[1],然后求出整个sum[]数组,然后dfs求出a[]数组。
完结。
总结:我觉得这题特别吼啊,没有考很难的知识点,考的是对问题的转化和把一个难以解决的问题先分解成一个一个可以解决的小问题,再合并起来。 %%%liu_runda
在来说一下自己,感觉就是考场上想的很不深入,好像就没有打算去肝正解,一直在很表层停留,这一定要改阿。
最后一点:临接表数组要开2背啊啊啊啊啊!!!
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<cstdio>
#include<cmath>
using namespace std;
#define int long long
const int N=1e5+;
int n,m;
int first[N],nex[N],to[N],tot,total;
int a[N],b[N],d[N],sum,vis[N],ansb[N],ansa[N],size[N],dt[N],v[N],vi[N],res[N];
inline void add(int a,int b){ to[++tot]=b,nex[tot]=first[a],first[a]=tot;}
void init(){
tot=;
memset(first,,sizeof(first));
memset(to,,sizeof(to));
memset(nex,,sizeof(nex));
//memset(a,0,sizeof(a));
//memset(b,0,sizeof(b));
//memset(ansb,0,sizeof(ansb));
//memset(ansa,0,sizeof(ansa));
sum=,total=;
memset(dt,,sizeof(dt));
memset(size,,sizeof(size));
//memset(vis,0,sizeof(vis));
//memset(vi,0,sizeof(vi));
//memset(v,0,sizeof(v));
memset(res,,sizeof(res));
memset(d,,sizeof(d));
//memset(vic,0,sizeof(vic));
}
void dfs(int x,int fa){
vis[x]=;
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(fa==y) continue;
d[y]=d[x]+;
dfs(y,x);
size[x]+=size[y];
}
}
void dfs_1(int x,int fa){
vis[x]=;
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(fa==y) continue;
ansb[y]=ansb[x]+sum-*size[y];
dfs_1(y,x);
}
}
void dfs_2(int x,int fa){
v[x]=;
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(fa==y) continue;
dt[y]=b[y]-b[x];
dfs_2(y,x);
}
}
void dfs_3(int x,int fa){
vi[x]=;
for(int i=first[x];i;i=nex[i]){
int y=to[i];
if(fa==y) continue;
ansa[x]-=res[y];
dfs_3(y,x);
}
}
signed main(){
int T;
scanf("%lld",&T);
while(T--){
init();
scanf("%lld",&n);
for(int i=;i<n;i++){
int x,y;
scanf("%lld%lld",&x,&y);
add(x,y);
add(y,x);
}
int opt;
scanf("%lld",&opt);
if(opt==){
for(int i=;i<=n;i++) {scanf("%lld",&a[i]);sum+=a[i];size[i]=a[i];}
d[]=;
dfs(,);
for(int i=;i<=n;i++) ansb[]+=a[i]*(d[i]-);
memset(vis,,sizeof(vis));
dfs_1(,);
for(int i=;i<=n;i++) printf("%lld ",ansb[i]);
puts("");
}
else{
for(int i=;i<=n;i++) scanf("%lld",&b[i]);
dfs_2(,);
//for(int i=2;i<=n;i++) cout<<dt[i]<<" ";
//cout<<endl;
total=;
for(int i=;i<=n;i++) total+=dt[i];
//cout<<total<<endl;
res[]=(*b[]+total)/(n-);
for(int i=;i<=n;i++) res[i]=(res[]-dt[i])/;
for(int i=;i<=n;i++) ansa[i]=res[i];
dfs_3(,);
for(int i=;i<=n;i++) printf("%lld ",ansa[i]);
puts("");
}
}
}
HZOJ 20190727 T2 单(树上dp+乱搞?+乱推式子?+dfs?)的更多相关文章
- codeforces 664B B. Rebus(乱搞题)
题目链接: B. Rebus time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】
黑白图像直方图 发布时间: 2017年7月9日 18:30 最后更新: 2017年7月10日 21:08 时间限制: 1000ms 内存限制: 128M 描述 在一个矩形的灰度图像上,每个 ...
- Playrix Codescapes Cup (Codeforces Round #413, rated, Div. 1 + Div. 2)(A.暴力,B.优先队列,C.dp乱搞)
A. Carrot Cakes time limit per test:1 second memory limit per test:256 megabytes input:standard inpu ...
- CF809E Surprise me!(莫比乌斯反演+Dp(乱搞?))
题目大意: 给你一棵树,树上的点编号为\(1-n\).选两个点\(i.j\),能得到的得分是\(\phi(a_i*a_j)*dis(i,j)\),其中\(dis(i,j)\)表示\(a\)到\(b\) ...
- VIJOS1476 旅行规划(树形Dp + DFS暴力乱搞)
题意: 给出一个树,树上每一条边的边权为 1,求树上所有最长链的点集并. 细节: 可能存在多条最长链!最长链!最长链!重要的事情说三遍 分析: 方法round 1:暴力乱搞Q A Q,边权为正-> ...
- 2016 10 28考试 dp 乱搞 树状数组
2016 10 28 考试 时间 7:50 AM to 11:15 AM 下载链接: 试题 考试包 这次考试对自己的表现非常不满意!! T1看出来是dp题目,但是在考试过程中并没有推出转移方程,考虑了 ...
- 【bzoj4976】宝石镶嵌 乱搞+dp
题目描述 从$n$个数中选出$n-k$个,使得它们的二进制或(or)最大.输出这个值. 输入 第一行包含两个正整数$n,k(2\le n\le 100000,1\le k\le 100,k<n) ...
- Codeforces 1077E (二分乱搞或者dp)
题意:给你一个数组,可以从中选区若干种元素,但每种元素选区的个数前一种必须是后一种的2倍,选区的任意2种元素不能相同,问可以选取最多的元素个数是多少? 思路1(乱搞):记录一下每种元素的个数,然后暴力 ...
- 学渣乱搞系列之dp斜率优化
学渣乱搞系列之dp斜率优化 By 狂徒归来 貌似dp的斜率优化一直很难搞啊,尤其是像我这种数学很挫的学渣,压根不懂什么凸包,什么上凸下凸的,哎...说多了都是泪,跟wdd讨论了下,得出一些结论.本文很 ...
随机推荐
- c++11 跨平台多线程demo和qt 静态链接(std::thread有join函数,设置 QMAKE_LFLAGS = -static)
#include <stdio.h>#include <stdlib.h> #include <chrono> // std::chrono::seconds#in ...
- Rust 优劣势: v.s. C++ / v.s. Go(持续更新)
Rust 发展速度比 C++ 强很多.如果去翻 open-std 的故纸堆,会发现 C++ 这边有很多人(包括标准委员会的人)提了有用的提案,但后来大多不了了之或经历了非常长的时间才进入标准. > ...
- Gluster的搭建和使用
Gluster的搭建和使用 序言 我们为什么要去使用分布式存储,在一家大型公司或者大规模的集群中,大家可能会经常遇到一个问题,我的数据怎么存放,放在那,数据空间不够了怎么办,这些问题经常困扰着我们. ...
- IntelliJ IDEA Spring boot devtools 实现热部署
一.spring-boot-devtools是一个为开发者服务的一个模块,其中最重要的功能就是自动部署新代码. 二.原理 使用了两个ClassLoader,一个ClassLoader用来加载那些不会变 ...
- MVC4学习要点记三
一.数据迁移用来解决code first情况下当增加.删除.改变实体类,或改变DbContext类后,相应地更新数据库结构而不会对现有数据产生影响. 1.启用迁移指令:enable-migration ...
- 异常-try...catch的方式处理异常2
package cn.itcast_02; /* * A:一个异常 * B:二个异常的处理 * a:每一个写一个try...catch * b:写一个try,多个catch * try{ * ... ...
- qt tableview使用
Qt::CheckState checkSibling(QStandardItem * item); void treeItem_checkAllChild(QStandardItem * item, ...
- 用最少的JS代码写出贪吃蛇游戏---迷你版
游戏进行页面展示 GAME OVER 页面展示 代码如下: <!doctype html> <html> <body> <canvas id=&q ...
- sqoop 安装
Sqoop是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql.postgresql...)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ,Oracle , ...
- php--常见算法3
<?php function leijia($number){ $arr=[]; for($i=1;$i<=$number;$i++) { for($j=1;$j<=$number; ...