本题属于二和一问题 子问题相互对称

考虑对于问题一:知a求b

  那么根据b数组定义式 显然能发现问题在于如何求dis(最短路)

  有很多算法可供选择 dijsktra,floyed,bfs/dfs,spfa等

  然而我们发现本题一个特点为边权相等(1) 显然应用dfs/bfs算法时间复杂度优于传统求最短路算法

考虑对于问题二:知b求a

  同样,我们能很快明确高斯消元算法并且也需要计算dis数组

然而 观察数据范围 T<=5, 2<=n<=100000,1<=u,v<=n

  显然这道题正解并不是高斯消元与最短路算法 因为空间与时间复杂度完全不可能(将dis数组转为一维 对于问题一能解决dis数组空间限制 然而对于其余关键算法无能为力)

那么在考场上正确的策略显然是对暴力求法进行优化而不是一味追求正解 顺着这个思路继续思考

考虑对于问题一:

  算法瓶颈在于求解最短路的时间空间问题 分析数据范围我们发现至少复杂度要降低一个维度才可行

  这启发我们利用递推方式求解 加之以本题是树形结构 思路就逐渐明了:二次扫描与换根法(对于NOIP模拟级习题 本算法显然不必多讲)

  那么思维方向已现 考虑节点转移对于b数组的影响可推出 b[node[i].to] = b[from] + sum_w - w[node[i].to] * 2(其中w[i]代表已i为跟节点子树sigma(a))依次优化复杂度

考虑对于问题二:

  尽管高斯消元不可行 但问题本质仍然为对b[i]的求解 也就是说同样需要消元求解

  问题一的解法启发我们问题二应该也与树形结构有关

  类比问题一 我们考虑节点转移对a数组的影响很容易得出 b[node[i].to] - b[from] = sum_w - w[node[i].to] * 2;

  至此我们推出了将b[2]~b[n]与w[2]~w[n]联系在一起的式子 很容易想到要求b[1]与这些量之间的关系 易得 b[1] = sigma(w[i]) (i!=1)

  显然连接纽带在于w数组 初等变换得 sigma(b[node[i].to - b[from]) = (n - 1)*sum_w - 2*sigma(w[i]) 代入b[1]得 sigma(b[node[i],to - b[from]]) + 2*b[1] = (n - 1)*sum_w;

  代入求得sum_w 在将sum_w代回原式可解出w[i]

  根据w[i]的定义 可知求解a数组只需要对w数组做差分即可

  代码如下(主要是思路 代码无难度 建议练习)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define I int
4 #define LL long long
5 #define B bool
6 #define C char
7 #define RE register
8 #define V void
9 #define L inline
10
11 const I MAXN = 100010;
12 I T,t,x,y,n;
13 LL a[MAXN],b[MAXN],sum[MAXN];
14 I num,head[MAXN];
15 LL SUM;
16 B jud[MAXN];
17 struct LYM
18 {
19 I to,next;
20 }node[MAXN << 1];
21 L I read(); L V store(I,I);
22 V dfs1(I); V dfs2(I); V dfs3(I); V dfs4(I);
23 signed main()
24 {
25 T = read();
26 while(T -- ){
27 n = read();
28 for(RE I i(1);i < n; ++ i){
29 x = read(),y = read();
30 store(x,y),store(y,x);
31 }
32 t = read();
33 if(t)
34 {
35 for(RE I i(1);i <= n; ++ i) b[i] = read();
36 dfs3(1); SUM += b[1] * 2; SUM /= n - 1;
37 sum[1] = SUM; dfs4(1);
38 for(RE I i(1);i <= n; ++ i) printf("%lld ",a[i]);
39 }
40 else
41 {
42 for(RE I i(1);i <= n; ++ i) a[i] = read();
43 dfs1(1);
44 for(RE I i(2);i <= n; ++ i) b[1] += sum[i];
45 dfs2(1);
46 for(RE I i(1);i <= n; ++ i) printf("%lld ",b[i]);
47 }
48 printf("\n");
49 num = 0,SUM = 0;
50 memset(head,0,sizeof(head));
51 memset(sum,0,sizeof(sum));
52 memset(a,0,sizeof(a));
53 memset(b,0,sizeof(b));
54 }
55 }
56 L I read()
57 {
58 RE I x(0),y(1); RE C z = getchar();
59 while(!isdigit(z)) y |= z == '-',z = getchar();
60 while(isdigit(z)) x = (x << 3) + (x << 1) + (z ^ 48),z = getchar();
61 return x * y;
62 }
63 L V store(I from,I to)
64 {
65 node[++num].to = to;
66 node[num].next = head[from];
67 head[from] = num;
68 }
69 V dfs1(I from){
70 jud[from] = 1;
71 sum[from] += a[from];
72 for(RE I i(head[from]); i ;i = node[i].next){
73 if(!jud[node[i].to]){
74 dfs1(node[i].to);
75 sum[from] += sum[node[i].to];
76 }
77 }
78 jud[from] = 0;
79 }
80 V dfs2(I from){
81 jud[from] = 1;
82 for(RE I i(head[from]); i ;i = node[i].next){
83 if(!jud[node[i].to]){
84 b[node[i].to] = b[from] + sum[1] - (sum[node[i].to] << 1);
85 dfs2(node[i].to);
86 }
87 }
88 jud[from] = 0;
89 }
90 V dfs3(I from){
91 jud[from] = 1;
92 for(RE I i(head[from]); i ;i = node[i].next){
93 if(!jud[node[i].to]){
94 SUM += b[node[i].to] - b[from];
95 dfs3(node[i].to);
96 }
97 }
98 jud[from] = 0;
99 }
100 V dfs4(I from){
101 jud[from] = 1;
102 LL tool = sum[from];
103 for(RE I i(head[from]); i ;i = node[i].next){
104 if(!jud[node[i].to]){
105 sum[node[i].to] = (SUM - b[node[i].to] + b[from]) >> 1;
106 dfs4(node[i].to);
107 tool -= sum[node[i].to];
108 }
109 }
110 a[from] = tool;
111 jud[from] = 0;
112 }

NOIP 模拟4 T2的更多相关文章

  1. noip模拟6(T2更新

    由于蒟弱目前还没调出T1和T2,所以先写T3和T4.(T1T2更完辣! update in 6.12 07:19 T3 大佬 题目描述: 他发现katarina大佬真是太强了,于是就学习了一下kata ...

  2. 20161003 NOIP 模拟赛 T2 解题报告

    Weed duyege的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹. 为了查出真相,duyege 准备修好电脑之后再进行一次金坷垃的模拟实验. 电脑上面有若干层金坷垃,每次只能在上面撒上一层高度为 ...

  3. 20161023 NOIP 模拟赛 T2 解题报告

    Task 2.回文串计数 (calc.pas/calc.c/calc.cpp) [题目描述] 虽然是一名理科生,Mcx常常声称自己是一名真正的文科生.不知为何,他对于背诵总有一种莫名的热爱,这也促使他 ...

  4. 20161005 NOIP 模拟赛 T2 解题报告

    beautiful 2.1 题目描述 一个长度为 n 的序列,对于每个位置 i 的数 ai 都有一个优美值,其定义是:找到序列中最 长的一段 [l, r],满足 l ≤ i ≤ r,且 [l, r] ...

  5. 神奇的NOIP模拟赛 T2 LGTB 学分块

    LGTB 学分块 LGTB 最近在学分块,但是他太菜了,分的块数量太多他就混乱了,所以只能分成3 块今天他得到了一个数组,他突然也想把它分块,他想知道,把这个数组分成3 块,块可以为空.假设3 块各自 ...

  6. 2018.02.12 noip模拟赛T2

    二兵的赌注 Description游戏中,二兵要进入了一家奇怪的赌场.赌场中有n个庄家,每个庄家都可以猜大猜小,猜一次一元钱.每一次开彩前,你都可以到任意个庄家那里下赌注.如果开彩结果是大,你就可以得 ...

  7. ztz11的noip模拟赛T2:查房

    链接: https://www.luogu.org/problemnew/show/U46611 思路: 这道题告你n-1条边就是骗你的 部分分也是骗你的 这道题连对边5分钟的事 一个点对另一个点有影 ...

  8. 2018.10.30 NOIp模拟赛T2 数字对

    [题目描述] 小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题.        她的面前浮现出一个长度为 n 的序列{ai},她想找出一段区间[L, R](1 <= L <= ...

  9. NOIP模拟18 T2

    不知道为什么很多人拒绝这题打搜索...其实搜索在充分剪枝后时间是非常优秀的,不管数据怎样基本都可跑出 首先一个显然结论:对于某种状态,他抓到的小精灵一定是一个连续的区间. 因此我们可以枚举这个区间的左 ...

随机推荐

  1. 通过中转DLL函数实现DLL劫持

    当我们运行程序时,一般情况下会默认加载Ntdll.dll和Kernel32.dll这两个链接库,在进程未被创建之前Ntdll.dll库就被默认加载了,三环下任何对其劫持都是无效的,除了该Dll外,其他 ...

  2. 手动脱ORiEN壳实战

    作者:Fly2015 ORiEN这种壳之前没有接触,到底是压缩壳还是加密壳也不知道,只能试一试喽.需要脱壳的程序是吾爱破解脱壳练习第7期的题目. 首先对加壳程序进行查壳,这一步也是程序脱壳的必要的一步 ...

  3. UVA11300分金币

    题意:      圆桌旁作者n个人,每个人都有一定数量的金币,他们每次可以给相邻的人一枚金币(可以给多次),问所有人金币数都相同的话最少要给多少次金币.思路:       这个题目感觉很好,首先我们可 ...

  4. UVA11019KMP(二维矩阵匹配出现次数)

    题意:     给你两个矩阵,一个大的一个小的,然后问你这个小矩阵在大的矩阵里出现了多少次? 思路:       说好了AC自动机的,我自己尝试写了个暴力的KMP竟然过了,AC自动机自己的模板还没写完 ...

  5. Windows核心编程 第五章 作业(下)

    5.4 查询作业统计信息 前面已经介绍了如何使用 Q u e r y I n f o r m a t i o n J o b O b j e c t函数来获取对作业的当前限制信息.也可以使用它来获取关 ...

  6. 2020年电子设计大赛F题

    挺简单前一百分得了九十多 当然主要是队友很给力 1 温度判别 MLX90614DCC,然后测温拟合吧...从五十度到三十度平均一次要测一个半小时...这是真的痛苦...然后虽然文件里面说自带测温工具, ...

  7. 【ECharts】报表联动,动态数据设计

    说明: 数据没有拉取后台数据,仅仅前端模拟数据,Copy即可有效果.联动后台时,使用异步获取数据即可.鼠标点击,动态展示点击项的数据.有关更多实例,请移步到echarts官网查看. 成果展示: 相关代 ...

  8. Python数模笔记-Sklearn(3)主成分分析

    主成分分析(Principal Components Analysis,PCA)是一种数据降维技术,通过正交变换将一组相关性高的变量转换为较少的彼此独立.互不相关的变量,从而减少数据的维数. 1.数据 ...

  9. Codeforces Round #691 (Div. 2)

    A. Red-Blue Shuffle 题意:有两个长度为n的数组,数组a和数组b,问那个数组中的数字相比之下比另一个数组中相应位置的元素值更大一些,如果数组a大就输出RED,如果数组b大就输出BLU ...

  10. SQLFlow的几种关系

    SQLFlow的几种关系 SQLFlow可以用来分析各种数据对象之间的依赖关系,其中包含了fdd, fdr, frd, join 四种关系 fdd:表示数据从源列到目标列的关系 frd:表示结果集返回 ...