CF1140G Double Tree

题解
首先如果我们要确定出每个\(dis_{i \to i+1 , i \in odd}\)
这个可以用两遍树形\(DP\)来解决
一遍是考虑走子树子树绕过来的
一遍是考虑从走祖先绕过来的
然后就可以考虑用倍增来解决了
设\(st1[u][i][0/1][0/1]\)表示从点\(u\)开始向上跳\(2^j\)步,开始的位置位于左/右边的树,结束的位置位于左/右边的树
倍增的时候就用两个数组\(dp1[0/1]/dp2[0/1]\)表示从\(u/v\)到左/右边树的\(LCA\)
不断往上跳着更新即可
注意要先把\(dp1/dp2\)的数组的值记录下来再用记录的值更新==
代码
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
# define LL long long
const int M = 300005 ;
const LL INF = 1e18 ;
using namespace std ;
inline LL read() {
char c = getchar() ; LL x = 0 , w = 1 ;
while(c>'9'||c<'0') { if(c=='-') w = -1 ; c = getchar() ; }
while(c>='0'&&c<='9') { x = x*10+c-'0' ; c = getchar() ; }
return x*w ;
}
int n , lg[M] , dep[M] ;
LL w[M] , st[M][22] , st1[M][22][2][2] , dp1[2] , dp2[2] ;
struct Node { int v ; LL w1 , w2 ; } ;
vector < Node > vec[M] ;
void dfs1(int u , int father) {
LL w1 , w2 ;
st[u][0] = father ; dep[u] = dep[father] + 1 ;
for(int i = 0 , v ; i < vec[u].size() ; i ++) {
v = vec[u][i].v , w1 = vec[u][i].w1 , w2 = vec[u][i].w2 ;
if(v == father) continue ; dfs1(v , u) ;
w[u] = min( w[u] , w[v] + w1 + w2 ) ;
}
}
void dfs2(int u , int father) {
LL w1 , w2 ;
for(int i = 0 , v ; i < vec[u].size() ; i ++) {
v = vec[u][i].v , w1 = vec[u][i].w1 , w2 = vec[u][i].w2 ;
if(v == father) continue ;
w[v] = min( w[v] , w[u] + w1 + w2 ) ;
dfs2(v , u) ;
}
}
void dfs(int u , int father) {
LL w1 , w2 ;
for(int i = 0 , v ; i < vec[u].size() ; i ++) {
v = vec[u][i].v , w1 = vec[u][i].w1 , w2 = vec[u][i].w2 ;
if(v == father) continue ;
dfs(v , u) ;
st1[v][0][0][0] = min( w1 , w[v] + w2 + w[u] ) ;
st1[v][0][1][1] = min( w2 , w[u] + w1 + w[v] ) ;
st1[v][0][0][1] = min( w[v] + w2 , w1 + w[u] ) ;
st1[v][0][1][0] = min( w2 + w[u] , w[v] + w1 ) ;
}
}
inline int LCA(int u , int v) {
if(dep[u] < dep[v]) swap(u , v) ;
for(int i = lg[n] ; i >= 0 ; i --) if(dep[st[u][i]] >= dep[v]) u = st[u][i] ;
if(u == v) return u ;
for(int i = lg[n] ; i >= 0 ; i --) if(st[u][i] != st[v][i]) u = st[u][i] , v = st[v][i] ;
return st[u][0] ;
}
inline LL Solve(int x , int y) {
int u = ((x + 1) >> 1) , v = ((y + 1) >> 1) , lcap ;
if(dep[u] < dep[v]) {
swap(u , v) ;
swap(x , y) ;
}
lcap = LCA(u , v) ;
LL tp0 , tp1 ;
dp1[(x + 1) & 1] = 0 ; dp1[((x + 1) & 1) ^ 1] = w[u] ;
for(int i = lg[n] ; i >= 0 ; i --) {
if(dep[st[u][i]] >= dep[lcap]) {
tp0 = dp1[0] ; tp1 = dp1[1] ;
dp1[0] = min( tp0 + st1[u][i][0][0] , tp1 + st1[u][i][1][0] ) ;
dp1[1] = min( tp0 + st1[u][i][0][1] , tp1 + st1[u][i][1][1] ) ;
u = st[u][i] ;
}
}
u = v ;
dp2[(y + 1) & 1] = 0 ; dp2[((y + 1) & 1) ^ 1] = w[u] ;
for(int i = lg[n] ; i >= 0 ; i --) {
if(dep[st[u][i]] >= dep[lcap]) {
tp0 = dp2[0] , tp1 = dp2[1] ;
dp2[0] = min( tp0 + st1[u][i][0][0] , tp1 + st1[u][i][1][0] ) ;
dp2[1] = min( tp0 + st1[u][i][0][1] , tp1 + st1[u][i][1][1] ) ;
u = st[u][i] ;
}
}
return min(dp1[0] + dp2[0] , dp1[1] + dp2[1]) ;
}
int main() {
n = read() ;
for(int i = 2 ; i <= n ; i ++) lg[i] = lg[i >> 1] + 1 ;
for(int i = 1 ; i <= n ; i ++) w[i] = read() ;
LL w1 , w2 ;
for(int i = 1 , u , v ; i < n ; i ++) {
u = read() ; v = read() ; w1 = read() ; w2 = read() ;
vec[u].push_back( (Node) { v , w1 , w2 } ) ;
vec[v].push_back( (Node) { u , w1 , w2 } ) ;
}
memset(st1 , 31 , sizeof(st1)) ;
dfs1(1 , 0) ; dfs2(1 , 0) ; dfs(1 , 0) ;
for(int j = 1 ; j <= lg[n] ; j ++)
for(int u = 1 ; u <= n ; u ++) {
st[u][j] = st[st[u][j - 1]][j - 1] ;
st[u][j] = st[st[u][j - 1]][j - 1] ;
st1[u][j][0][0] = min( st1[u][j - 1][0][0] + st1[st[u][j - 1]][j - 1][0][0] , st1[u][j - 1][0][1] + st1[st[u][j - 1]][j - 1][1][0] ) ;
st1[u][j][0][1] = min( st1[u][j - 1][0][0] + st1[st[u][j - 1]][j - 1][0][1] , st1[u][j - 1][0][1] + st1[st[u][j - 1]][j - 1][1][1] ) ;
st1[u][j][1][0] = min( st1[u][j - 1][1][0] + st1[st[u][j - 1]][j - 1][0][0] , st1[u][j - 1][1][1] + st1[st[u][j - 1]][j - 1][1][0] ) ;
st1[u][j][1][1] = min( st1[u][j - 1][1][0] + st1[st[u][j - 1]][j - 1][0][1] , st1[u][j - 1][1][1] + st1[st[u][j - 1]][j - 1][1][1] ) ;
}
int Q = read() , x , y ;
while(Q --) {
x = read() ; y = read() ;
printf("%lld\n",Solve(x , y)) ;
}
return 0 ;
}
CF1140G Double Tree的更多相关文章
- Codeforces 1140G Double Tree 倍增 + dp
刚开始, 我以为两个点肯定是通过树上最短路径过去的, 无非是在两棵树之间来回切换, 这个可以用倍增 + dp 去维护它. 但是后来又发现, 它可以不通过树上最短路径过去, 我们考虑这样一种情况, 起点 ...
- @hdu - 6594@ Double Tree
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两棵 N 个点的树,以及树上每条边的权值 w(u, v),每 ...
- Codeforces 68D - Half-decay Tree
题意 有一颗高度为 \(h\) 的完全二叉树(即点数为 \(2^{h+1}-1\) ),有两种操作: add x y 给 \(x\) 点的权值加 \(y\) decay 一次衰变定义为选择一个叶子节点 ...
- 平衡树 替罪羊树(Scapegoat Tree)
替罪羊树(Scapegoat Tree) 入门模板题 洛谷oj P3369 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入xx数 删除xx数(若有多个相同 ...
- Color a Tree
题目链接:Click here Solution: 看起来不太能dp,则考虑树上贪心 题目要求一个点必须先染父亲才能染自己,就给了我们启示,贪心的合并点 我们定义一个点的权重为这个点的价值和/点数,然 ...
- CodeForces 602E【概率DP】【树状数组优化】
题意:有n个人进行m次比赛,每次比赛有一个排名,最后的排名是把所有排名都加起来然后找到比自己的分数绝对小的人数加一就是最终排名. 给了其中一个人的所有比赛的名次.求这个人最终排名的期望. 思路: 渣渣 ...
- Educational Codeforces Round 62 (Rated for Div. 2) Solution
最近省队前联考被杭二成七南外什么的吊锤得布星,拿一场Div. 2恢复信心 然后Div.2 Rk3.Div. 1+Div. 2 Rk9,rating大涨200引起舒适 现在的Div. 2都怎么了,最难题 ...
- poj 1151 (未完成) 扫描线 线段树 离散化
#include<iostream> #include<vector> #include<cmath> #include<algorithm> usin ...
- codeforce 139E
成段更新+离散化才能过,数据好强.. 单点更新挂在了test27,下次做到成段更新再来做! /* 期望=存活概率*点权值/100 ans=sum(期望) 离散化树木权值,数轴统计累加可能倒下的树木概率 ...
随机推荐
- 无线网卡与本地连接不能同时使用&一机多网络的优先级设置
无线网卡与本地连接不能同时使用&一机多网络的优先级设置 2012-05-30 20:39 初次记录 2012-08-09 10:32 修订 题目中的两个问题,其实都可以归结为一个问题,即网络优 ...
- Office EXCEL 如何保留两位小数,四舍五入
选中若干单元格,然后右击设置单元格格式,数值中保留两位小数 使用round函数四舍五入,如下图所示,我在N10单元格中输入"ROUND(M10,1)"即可,其中ROUND是函数 ...
- bug集合及其解决方法
点击查看原文 1. java.lang.IllegalStateException: Expected a string but was BEGIN_ARRAY at line 1 column 27 ...
- Android使用adb获得activity堆栈信息
很实用的命令: adb shell dumpsys activity 该命令能够看到当前执行的是哪个activity,执行的一些进程等 首先能够看到执行的进程: ACTIVITY MANAGER RU ...
- 软件质量之道:PCLint之中的一个
故天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行拂乱其所为,所以动心忍性,增益其所不能. 孟子 1引子 今天听老韩一席话,当真是感慨万千啊.心怀斗志昂扬.奋斗十年,到头来.却看到身 ...
- UVA 10288 - Coupons(概率递推)
UVA 10288 - Coupons option=com_onlinejudge&Itemid=8&page=show_problem&category=482&p ...
- Selenium 工具介绍、安装、配置及使用
概念 selenium是一款跨平台开源工具,用于web的功能完整性測试,想做压力測试的能够换软件了 先看一眼官方站 http://docs.seleniumhq.org/download/ 首先要FQ ...
- 【iOS系列】-iOS的多线程解析
[iOS系列]-iOS的多线程解析 iOS的多线程实现技术: 1:GCD -- Grand Central Dispatch 是基于C语言的底层API 用Block定义任务,使用起来非常灵活便捷 提供 ...
- css hack原理
近期看了几篇关于css hack的文章,认为不错整理一下. css hack非常多人不理解它的原理,事实上大家都知道对于不同的浏览器,CSS的解析程度不一样.因此会导致生成的页面效果不一样:特别是对于 ...
- 【bzoj4401】块的计数
首先,块的大小确定的话,可以发现方案最多只有1种 然后就可以O(nsqrt(n))搞,不过会TLE 接着我们又发现,一个节点可以作一个块的根,当且仅当该节点的size能被块的大小整除 然后就可以O(n ...