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> ...
随机推荐
- 洛谷 P2858 [USACO06FEB]奶牛零食Treats for the Cows 题解
P2858 [USACO06FEB]奶牛零食Treats for the Cows 题目描述 FJ has purchased N (1 <= N <= 2000) yummy treat ...
- 01-复杂度2 Maximum Subsequence Sum (25 分)
Given a sequence of K integers { N1, N2, ..., NK }. A continuous subsequence is defined to ...
- 关于 Mercury_Lc 说明
现在还主要在用 csdn 写博客,博客地址:https://blog.csdn.net/Mercury_Lc 这个是因为好奇,点了一下 一键搬家 ,就酱紫了. 主要更新,前往这个网址 https:// ...
- JAVA中Stringbuffer的append( )方法
Stringbuffer是动态字符串数组,append( )是往动态字符串数组添加,跟“xxxx”+“yyyy”相当‘+’号. 跟String不同的是Stringbuffer是放一起的,String1 ...
- Java串口通信--------基于RXTX (附带资源地址)
最近帮老师做了一个小项目,一个牧场公司想用传感器收集一些环境信息,记录到数据库里去,然后加以分析查看.这里面和传感器通信用到了串口通信,我也是接触了一下,把用到的东西分享出来. 准备工作: RXTX: ...
- 美团-2019Q2述职总结
述职要求: 产品对平台化的规划并不清晰:内部因素:对SaaS平台的理解不够深刻: 对公司相关脚手架,服务搭建相关需要注意的点,有更深入的认识.对做系统服务的关注点有了更深入的理解. 功能权限的话: Q ...
- 第06组 Beta冲刺(4/4)
队名:福大帮 组长博客链接:https://www.cnblogs.com/mhq-mhq/p/11990575.html 作业博客 : https://edu.cnblogs.com/campus/ ...
- springMVC和struts2有什么不同?为什么要用springMVC或者struts2?让你实现一个MVC框架大概如何设计?
[问题一:不同] (1)框架机制 1.Struts2采用Filter(StrutsPrepareAndExecuteFilter)实现,SpringMVC(DispatcherServlet)则采用S ...
- ---iOS开发 截取字符串中两个指定字符串中间的字符串---
例如,要截取一个字符串中,两个指定字符串中间的字符串,OC截取方法如下: // 要截取 "> 和 </ 之间的汉字内容: @implementationViewControlle ...
- 123456123456#6#---###6%%%----com.zzj.DinosourKnown235---前拼show后广--恐龙百科-66666666
com.zzj.DinosourKnown235---前拼show后广--恐龙百科-