点分治+李超树

因为题目要求的是树上所有路径,所以用点分治维护

因为在点分治的过程中相当于将树上经过当前$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的更多相关文章

  1. [CF1303G] Sum of Prefix Sums - 点分治,李超线段树

    给定一棵 \(n\) 个点的带点权的树,求树上的路径 \(x_1,...,x_k\) ,最大化 \(\sum_{i=1}^k ia_{x_i}\) Solution 树上路径问题可用点分治. 考虑如何 ...

  2. Codeforces 1303G - Sum of Prefix Sums(李超线段树+点分治)

    Codeforces 题面传送门 & 洛谷题面传送门 个人感觉这题称不上毒瘤. 首先看到选一条路径之类的字眼可以轻松想到点分治,也就是我们每次取原树的重心 \(r\) 并将路径分为经过重心和不 ...

  3. CodeForces 837F - Prefix Sums | Educational Codeforces Round 26

    按tutorial打的我血崩,死活挂第四组- - 思路来自FXXL /* CodeForces 837F - Prefix Sums [ 二分,组合数 ] | Educational Codeforc ...

  4. 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]代表已经选择 ...

  5. 【题解】【数组】【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- ...

  6. 【题解】【数组】【Prefix Sums】【Codility】Passing Cars

    A non-empty zero-indexed array A consisting of N integers is given. The consecutive elements of arra ...

  7. Codeforces 837F Prefix Sums

    Prefix Sums 在 n >= 4时候直接暴力. n <= 4的时候二分加矩阵快速幂去check #include<bits/stdc++.h> #define LL l ...

  8. CodeForces 1204E"Natasha, Sasha and the Prefix Sums"(动态规划 or 组合数学--卡特兰数的应用)

    传送门 •参考资料 [1]:CF1204E Natasha, Sasha and the Prefix Sums(动态规划+组合数) •题意 由 n 个 1 和 m 个 -1 组成的 $C_{n+m} ...

  9. codeforces:Prefix Sums分析和实现

    题目大意: 给出一个函数P,P接受一个数组A作为参数,并返回一个新的数组B,且B.length = A.length + 1,B[i] = SUM(A[0], ..., A[i]).有一个无穷数组序列 ...

随机推荐

  1. This is Riv3r1and.

    总是要弄个博客来搞的嘛.

  2. Arduino读取写入电压值

    读取写入方式分为数字和模拟 读取方式:(注意接地) 数字:digitalRead(pin); 模拟:analogRead(A1);float val=value*(5.0/1023.0);       ...

  3. 【学习笔记/题解】分层图/[JLOI2011]飞行路线

    题目戳我 \(\text{Solution:}\) 关于分层图: 一般用于处理:给你\(k\)次机会对边权进行修改的最短路问题. 算法流程: 建立出\(k\)层图,对应进行\(k\)次操作后的局面. ...

  4. 利用Python+pyecharts+tushare图形化展示股票历史财务信息

    在微信或其他平台上,经常能看到别人推荐股票,分析的头头是道,让自己懊恼于没有早点关注到这只股票,好像错失了几个亿.但是投资股票又忌讳听消息跟风,总不能看到别人推荐自己就无脑买入. 看到了一只股票,自己 ...

  5. Tensorflow学习笔记No.0

    这里更新一些学习Tensorflow过程中可能用到的实用工具. Jupyter Notebook Jupyter Notebook 是一个非常方便的python编程工具,支持可视化,对于学习pytho ...

  6. Java安全之Commons Collections1分析(三)

    Java安全之Commons Collections1分析(三) 0x00 前言 继续来分析cc链,用了前面几篇文章来铺垫了一些知识.在上篇文章里,其实是硬看代码,并没有去调试.因为一直找不到JDK的 ...

  7. linux 内核参数设置 - sysctl

    sysctl 命令用于查看和修改内核参数 查看指定参数: sysctl kernel.threads-max 查看所有参数: sysctl -a 修改指定参数: sysctl -w kernel.th ...

  8. 多测试_常用linux命令_002

    linux 介绍 常用的操作系统(os): windows .dos.android.ios.unix.linux linux系统:是一个免费.开源的操作系统 支持多cpu,多用户,多线程的操作系统, ...

  9. 网络io控制器

    网络io控制器 网络io控制器 ZLAN6842,ZLAN6844是8路远程网络IO控制器.含有8路DI.8路DO,8路AI输入.其中DI支持干节点和湿节点,带光耦隔离:DO为继电器输出,具有5A 2 ...

  10. Android Jetpack从入门到精通(深度好文,值得收藏)

    前言 即学即用Android Jetpack系列Blog的目的是通过学习Android Jetpack完成一个简单的Demo,本文是即学即用Android Jetpack系列Blog的第一篇. 记得去 ...