Codechef TSUM2 Sum on Tree 点分治、李超线段树
点分治模板题都不会迟早要完
发现这道题需要统计所有路径的信息,考虑点分治统计路径信息。
点分治之后,因为路径是有向的,所以对于每一条路径都有向上和向下的两种。那么如果一条向上的路径,点数为\(s_1\),单独考虑这条路径的权值和为\(v_1\),和一条向下的路径,点权和为\(s_2\),单独考虑这条路径的权值和为\(v_2\),这两条路径进行拼接(分治中心算在向上路径中,这样\(s_1 > 0\)),那么拼接起来的路径的权值和就是\(s_1s_2 + v_1 + v_2\)。如果我们枚举到了一条向上的路径,对于每一条向下路径能够和这条向上路径拼接产生的贡献是一个一次函数的形式,同时横坐标范围在\(1\)到\(50000\)之间,所以可以使用李超线段树维护最值。
注意到来自同一棵子树的向上和向下路径不能拼接,所以对于每一棵子树,先把子树内所有向上路径统计完成,再把向下的路径放进李超树,从前往后做一遍再从后往前做一遍即可。
注意一下分治中心单独作为一条向上路径/向下路径为空的情况。
#include<bits/stdc++.h>
//this code is written by Itst
using namespace std;
int read(){
int a = 0; char c = getchar(); bool f = 0;
while(!isdigit(c)){f = c == '-'; c = getchar();}
while(isdigit(c)){a = a * 10 + c - 48; c = getchar();}
return f ? -a : a;
}
const int _ = 100003;
#define int long long
struct line{
int k , b;
line(int _k = -1e9 , int _b = -1e18) : k(_k) , b(_b){}
};
long double sect(line a , line b){return 1.0 * (b.b - a.b) / (a.k - b.k);}
namespace Tree{
line now[_ << 2];
#define mid ((l + r) >> 1)
#define lch (x << 1)
#define rch (x << 1 | 1)
void init(int x , int l , int r){
if(now[x].k != -1e9 || now[x].b != -1e18){
now[x] = line();
if(l != r){init(lch , l , mid); init(rch , mid + 1 , r);}
}
}
void ins(int x , int l , int r , line p){
line q = now[x];
if(q.k == p.k){now[x] = q.b > p.b ? q : p; return;}
if(p.k > q.k) swap(p , q);
long double t = sect(p , q);
if(t <= l){now[x] = q; return;}
if(t >= r){now[x] = p; return;}
if(t <= mid){
now[x] = q;
if(l != r) ins(lch , l , mid , p);
}
else{
now[x] = p;
if(l != r) ins(rch , mid + 1 , r , q);
}
}
int calc(line A , int x){return A.k * x + A.b;}
int qry(int x , int l , int r , int tar){
if(l == r) return calc(now[x] , tar);
return max(calc(now[x] , tar) , mid >= tar ? qry(lch , l , mid , tar) : qry(rch , mid + 1 , r , tar));
}
}
struct Edge{
int end , upEd;
}Ed[_ << 1];
int head[_] , val[_] , cntEd , N , mnsz , mnid , nowsz , ans;
bool vis[_];
void addEd(int a , int b){
Ed[++cntEd] = (Edge){b , head[a]};
head[a] = cntEd;
}
void getsz(int x){
vis[x] = 1; ++nowsz;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]) getsz(Ed[i].end);
vis[x] = 0;
}
int getrt(int x){
int sz = 1 , mx = 1; vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
int t = getrt(Ed[i].end);
mx = max(mx , t); sz += t;
}
mx = max(mx , nowsz - sz);
if(mx < mnsz){mnsz = mx; mnid = x;}
vis[x] = 0; return sz;
}
void dfs1(int x , int sum , int sz , int v){
ans = max(ans , Tree::qry(1 , 1 , N , sz) + sum);
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]) dfs1(Ed[i].end , sum + val[Ed[i].end] + v , sz + 1 , val[Ed[i].end] + v);
vis[x] = 0;
}
void dfs2(int x , int sum , int sz , int v){
Tree::ins(1 , 1 , N , line(v , sum));
vis[x] = 1;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]) dfs2(Ed[i].end , sum + (sz + 1) * val[Ed[i].end] , sz + 1 , val[Ed[i].end] + v);
vis[x] = 0;
}
void solve(int x){
mnsz = 1e9; nowsz = 0;
getsz(x); getrt(x); vis[x = mnid] = 1;
Tree::init(1 , 1 , N); Tree::ins(1 , 1 , N , line(0 , 0));
vector < int > nxt;
for(int i = head[x] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
nxt.push_back(Ed[i].end);
dfs1(Ed[i].end , 2 * val[x] + val[Ed[i].end] , 2 , val[x] + val[Ed[i].end]);
dfs2(Ed[i].end , val[Ed[i].end] , 1 , val[Ed[i].end]);
}
ans = max(ans , Tree::qry(1 , 1 , N , 1) + val[x]); Tree::init(1 , 1 , N);
reverse(nxt.begin() , nxt.end());
for(auto t : nxt){
dfs1(t , 2 * val[x] + val[t] , 2 , val[x] + val[t]);
dfs2(t , val[t] , 1 , val[t]);
}
for(auto t : nxt) solve(t);
}
signed main(){
for(int T = read() ; T ; --T){
N = read(); cntEd = 0; ans = -1e18;
memset(vis , 0 , sizeof(bool) * (N + 1));
memset(head , 0 , sizeof(int) * (N + 1));
for(int i = 1 ; i <= N ; ++i) val[i] = read();
for(int i = 1 ; i < N ; ++i){
int a = read() , b = read(); addEd(a , b); addEd(b , a);
}
solve(1); printf("%lld\n" , ans);
}
return 0;
}
Codechef TSUM2 Sum on Tree 点分治、李超线段树的更多相关文章
- [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\) 并将路径分为经过重心和不 ...
- [CodeChef - STREETTA] The Street 李超线段树
大致题意: 给出两个序列A,B,A初始为负无穷,B初始为0,有三种操作 1.在A上区间[u,v]上加一个等差数列,取与原本A序列的最大值. 2.在B上区间[u,v]上加一个等差数列. 3.给出一个点X ...
- 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交
4515: [Sdoi2016]游戏 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 129[Submit][Status][ ...
- 【BZOJ-3165】Segment 李超线段树(标记永久化)
3165: [Heoi2013]Segment Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 368 Solved: 148[Submit][Sta ...
- 【BZOJ-1568】Blue Mary开公司 李超线段树 (标记永久化)
1568: [JSOI2008]Blue Mary开公司 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 557 Solved: 192[Submit ...
- Codeforces Round #463 F. Escape Through Leaf (李超线段树合并)
听说正解是啥 set启发式合并+维护凸包+二分 根本不会啊 , 只会 李超线段树合并 啦 ... 题意 给你一颗有 \(n\) 个点的树 , 每个节点有两个权值 \(a_i, b_i\) . 从 \( ...
- Luogu P4097 [HEOI2013]Segment 李超线段树
题目链接 \(Click\) \(Here\) 李超线段树的模板.但是因为我实在太\(Naive\)了,想象不到实现方法. 看代码就能懂的东西,放在这里用于复习. #include <bits/ ...
- BZOJ 3165 李超线段树
思路: 李超线段树 我是把线段转成斜率的形式搞得 不知道有没有更简单的方法 //By SiriusRen #include <cmath> #include <cstdio> ...
随机推荐
- 【JOISC2019|2019】【20190622】cake3
题目 \(N\) 个物品中选\(M\)个,排列成一个环:\(k_1,\cdots,k_M\)价值为: \[ \sum_{j=1}^{N}{V_i} - \sum_{j=1}^{M}|C_{k_j}- ...
- 什么是uni-app?
uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码,可发布到iOS.Android.H5.以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台. 即使不跨 ...
- 微信小程序地图组件
index.wxml <map id="map" markers="{{markers}}" longitude="{{longitude}}& ...
- msyql8.0编译安装
1.安装依赖 yum -y install wget cmake gcc gcc-c++ncurses ncurses-devel libaio-devel openssl openssl-d ...
- ICEM-带孔小板
原版视频下载地址:https://pan.baidu.com/s/1jHMvXHG 密码: p93q
- 2019 SDN第五次上机作业
2019 SDN第五次上机作业 作业链接 1.浏览RYU官网学习RYU控制器的安装和RYU开发入门教程,提交对于教程代 码的理解,包括但不限于: 安装RYU控制器并测试 安装教程 安装过程及遇到各种问 ...
- web编辑器的使用比较
一开始测试的时候发现都还可以,只是出于后续考虑,选择了ckeditor,但是有时候会莫名出现Cannot read property 'XXX' of undefined,如下: Uncaught T ...
- np.concatenate
- EF Core基本使用
Mysql: nuget 安装 Pomelo.EntityFrameworkCore.MySql Microsoft.EntityFrameworkCore.Design csprj 修改: < ...
- LODOP中打印项水平居中简短问答
相关博文:LODOP打印项水平居中(超文本纯文本居中)LODOP打印超文本有边距不居中的情况2(超文本居中的一种) LODOP表格水平居中3(宽度为百分比)(超文本居中的一种) LODOP打印图片水平 ...