CF1303G Sum of Prefix Sums
点分治+李超树
因为题目要求的是树上所有路径,所以用点分治维护
因为在点分治的过程中相当于将树上经过当前$root$的一条路径分成了两段
那么先考虑如何计算两个数组合并后的答案
记数组$a$,$b$,求得是将$b$数组接到$a$数组的答案
其$a$,$b$的sum of prefix sums分别为$sa$,$sb$,其中$a$数组所有元素的和为$sum$,$b$数组长度为$l$
然后整合一下原来计算的式
其实对于一个数组$P$的sum of prefix sums就是
$n*p_{1}+(n-1)*p_{2}+(n-2)*p_{3}+...+2*p_{n-1}+1*p_{n}$
照着这个式子推出来,将$b$数组接到$a$数组的答案是
$sa+sb+sum*l$
然后这里可以将$sa$看做截距,$sum$看做斜率,$l$为$x$坐标,最终答案为$y$坐标
求的就是每一个$sa$为截距,$sum$为斜率的线段在某一点的最大取值
那么用李超树维护即可
要注意对于树上两个节点$u$,$v$
$u$到$v$的答案和$v$到$u$的答案是不一样的
所以要在合并子树的时候要正着扫一遍,反着扫一遍
还有如果是只有一颗子树需要特判
1 #pragma GCC optimize(2)
2 #include <bits/stdc++.h>
3 #define int long long
4 using namespace std;
5 const int N=150100;
6 int n,a[N];
7 int sz[N],vi[N],dfn,MAX,root;
8 vector <int> e[N];
9 struct line
10 {
11 int k,b;
12 };
13 struct node
14 {
15 line tag;
16 int ti;
17 }sh[N*4];
18 int cal(int x,line a)
19 {
20 return a.k*x+a.b;
21 }
22 void change(int x,int l,int r,line k)
23 {
24 if (sh[x].ti!=dfn)
25 {
26 sh[x].tag=k;
27 sh[x].ti=dfn;
28 return;
29 }
30 if (cal(l,k)>=cal(l,sh[x].tag) && cal(r,k)>=cal(r,sh[x].tag))
31 {
32 sh[x].tag=k;
33 return;
34 }
35 if (cal(l,k)<=cal(l,sh[x].tag) && cal(r,k)<=cal(r,sh[x].tag))
36 return;
37 int mid=(l+r)>>1;
38 if (cal(mid,k)>cal(mid,sh[x].tag)) swap(k,sh[x].tag);
39 if (cal(l,k)>cal(l,sh[x].tag)) change(x+x,l,mid,k);
40 else change(x+x+1,mid+1,r,k);
41 }
42 int query(int x,int l,int r,int wh)
43 {
44 int ans=(sh[x].ti==dfn)?cal(wh,sh[x].tag):0;
45 if (l==r) return ans;
46 int mid=(l+r)>>1;
47 if (wh<=mid) ans=max(ans,query(x+x,l,mid,wh));
48 else ans=max(ans,query(x+x+1,mid+1,r,wh));
49 return ans;
50 }
51 //李超树
52 void dfs_insert(int x,int fa,int de,line now)
53 {
54 now.k+=a[x];
55 now.b+=de*a[x];
56 change(1,1,n,now);
57 for (register int i=0;i<(int)e[x].size();i++)
58 {
59 int u=e[x][i];
60 if (vi[u] || u==fa) continue;
61 dfs_insert(u,x,de+1,now);
62 }
63 }
64 void dfs_query(int x,int fa,int de,int sb,int s)
65 {
66 sb+=a[x]+s;
67 s+=a[x];
68 MAX=max(MAX,query(1,1,n,de)+sb);
69 for (register int i=0;i<(int)e[x].size();i++)
70 {
71 int u=e[x][i];
72 if (vi[u] || u==fa) continue;
73 dfs_query(u,x,de+1,sb,s);
74 }
75 }
76 void dfs_size(int x,int fa)
77 {
78 sz[x]=1;
79 for (register int i=0;i<(int)e[x].size();i++)
80 {
81 int u=e[x][i];
82 if (vi[u] || u==fa) continue;
83 dfs_size(u,x);
84 sz[x]+=sz[u];
85 }
86 }
87 void dfs_root(int x,int fa,int tot)
88 {
89 bool bl=1;
90 for (register int i=0;i<(int)e[x].size();i++)
91 {
92 int u=e[x][i];
93 if (vi[u] || u==fa) continue;
94 dfs_root(u,x,tot);
95 if (sz[u]>tot/2) bl=0;
96 }
97 if (tot-sz[x]>tot/2) bl=0;
98 if (bl) root=x;
99 }
100 void dfs(int x,int fa,int de,int sa,int sb,int s)
101 {
102 sa+=de*a[x];
103 sb+=s+a[x];
104 s+=a[x];
105 MAX=max(MAX,sb);
106 MAX=max(MAX,sa);
107 for (register int i=0;i<(int)e[x].size();i++)
108 {
109 int u=e[x][i];
110 if (vi[u] || u==fa) continue;
111 dfs(u,x,de+1,sa,sb,s);
112 }
113 }
114 void divide(int x)//点分治
115 {
116 dfn++;
117 vi[x]=1;
118 int cnt=0;
119 for (register int i=0;i<(int)e[x].size();i++)
120 {
121 int u=e[x][i];
122 if (vi[u]) continue;
123 cnt++;
124 line tmp;
125 tmp.k=tmp.b=0;
126 if (cnt!=1) dfs_query(u,x,2,a[x],a[x]);
127 dfs_insert(u,x,1,tmp);
128 }
129 bool bl=(cnt==1);
130 dfn++;cnt=0;
131 for (register int i=(int)e[x].size()-1;i>=0;i--)//反着扫描
132 {
133 int u=e[x][i];
134 if (vi[u]) continue;
135 if (bl) dfs(u,x,2,a[x],a[x],a[x]);//只有一颗子树时的特判
136 cnt++;
137 line tmp;
138 tmp.k=tmp.b=0;
139 if (cnt!=1) dfs_query(u,x,2,a[x],a[x]);
140 dfs_insert(u,x,1,tmp);
141 }
142 for (register int i=0;i<(int)e[x].size();i++)
143 {
144 int u=e[x][i];
145 if (vi[u]) continue;
146 dfs_size(u,x);
147 dfs_root(u,x,sz[u]);
148 divide(root);
149 }
150 }
151 signed main()
152 {
153 scanf("%lld",&n);
154 for (int i=1;i<n;i++)
155 {
156 int u,v;
157 scanf("%lld%lld",&u,&v);
158 e[u].push_back(v);
159 e[v].push_back(u);
160 }
161 for (int i=1;i<=n;i++)
162 {
163 scanf("%lld",&a[i]);
164 MAX=max(MAX,a[i]);
165 }
166 dfs_size(1,-1);
167 dfs_root(1,-1,sz[1]);
168 divide(root);
169 printf("%lld\n",MAX);
170 }
CF1303G Sum of Prefix Sums的更多相关文章
- [CF1303G] Sum of Prefix Sums - 点分治,李超线段树
给定一棵 \(n\) 个点的带点权的树,求树上的路径 \(x_1,...,x_k\) ,最大化 \(\sum_{i=1}^k ia_{x_i}\) Solution 树上路径问题可用点分治. 考虑如何 ...
- Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)
Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...
- CodeForces 837F - Prefix Sums | Educational Codeforces Round 26
按tutorial打的我血崩,死活挂第四组- - 思路来自FXXL /* CodeForces 837F - Prefix Sums [ 二分,组合数 ] | Educational Codeforc ...
- Educational Codeforces Round 26 [ D. Round Subset ] [ E. Vasya's Function ] [ F. Prefix Sums ]
PROBLEM D - Round Subset 题 OvO http://codeforces.com/contest/837/problem/D 837D 解 DP, dp[i][j]代表已经选择 ...
- 【题解】【数组】【Prefix Sums】【Codility】Genomic Range Query
A non-empty zero-indexed string S is given. String S consists of N characters from the set of upper- ...
- 【题解】【数组】【Prefix Sums】【Codility】Passing Cars
A non-empty zero-indexed array A consisting of N integers is given. The consecutive elements of arra ...
- Codeforces 837F Prefix Sums
Prefix Sums 在 n >= 4时候直接暴力. n <= 4的时候二分加矩阵快速幂去check #include<bits/stdc++.h> #define LL l ...
- CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)
传送门 •参考资料 [1]:CF1204E Natasha, Sasha and the Prefix Sums(动态规划+组合数) •题意 由 n 个 1 和 m 个 -1 组成的 $C_{n+m} ...
- codeforces:Prefix Sums分析和实现
题目大意: 给出一个函数P,P接受一个数组A作为参数,并返回一个新的数组B,且B.length = A.length + 1,B[i] = SUM(A[0], ..., A[i]).有一个无穷数组序列 ...
随机推荐
- 多线程循环打印数组 -- Java笔记
问题描述: 现有多个长度相同的数组,现要求使用多线程将数组内的数交替打印. 如: int[] ai = {1,2,3,4,5,6,7}; String[] ac = {"A",&q ...
- ASP。使用依赖注入的asp.net Core 2.0用户角色库动态菜单管理
下载source code - 2.2 MB 介绍 在开始这篇文章之前,请阅读我的前一篇文章: 开始使用ASP.NET Core 2.0身份和角色管理 在上一篇文章中,我们详细讨论了如何使用ASP.N ...
- Consul 快速入门
Consul是什么 Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用.限流.熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便.它提供了一个功 ...
- Candy (candy)
Description Due to its great contribution to the maintenance of world peace, Dzx was given an unlimi ...
- Angular8 ie兼容性解决
启用腻子脚本 polyfills.ts /* IE9, IE10 and IE11 requires all of the following polyfills. */ import 'core-j ...
- 推荐几款好用的python编辑器
1.自带的IDLE: (1)交互式代码编辑.在>>>提示符后输入python代码,按Enter键就可以显示代码命令执行结果. (2)脚本式代码编辑.选择File菜单里的newFil ...
- 多测师_讲解python__004 函数
# 函数:一个工具,随调随用# 降级代码冗余## 增加代码的复用性,提高开发效率,为了不成为cv战士## 提高程序扩展性## 函数有两个阶段:定义阶段,调用阶段.## 定义时:只检查函数体内代码语法, ...
- Istio多集群(1)-多控制面
Istio多集群(1)-多控制面 参考自官方文档. 目录 Istio多集群(1)-多控制面 复制控制面 要求 在每个集群中部署Istio控制面 配置DNS 配置应用服务 配置用例服务 卸载 FAQ 复 ...
- Redis的介绍以及安装
redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库,缓存和消息中间件 高速缓存介绍 高速缓存利用内存保存数据,读写速度远超硬盘 高速缓存可以减少 I/O 操作,降 ...
- 第4天 | 12天搞定Python,基础语法(下)
为了方便你的学习,减轻负重,我特意将基础语法分成上下两部分.希望你喜欢这种方式,如果不喜欢,你可以跟我说,反正我是不会改的,哈哈~~. 如果上部分,你还没看的话,先去看<第4天 | 12天搞定P ...