调了半天居然还能是线段树写错了,药丸

  这题大概是类似一个树形DP的东西。设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路。如果我们枚举每条路去转移,会发现这条路沿线上的其他子树的答案难以统计,那怎么办呢,我们可以让这条路向上回溯的时候顺便记录一下,于是有$val[i]$表示必修i这条路,并且修完当前子树的最小代价。

  则有转移$dp[x]=min(val[j])$,且$j$这条路必须覆盖$x$。

  $val[i]=(\sum dp[son])-dp[sonx]+val[i]$,且$i$这条路必须覆盖$sonx$。

  转移用线段树来维护就好,至于怎么判断某条路是否覆盖两个点,只要递归到某条路的起点的时候把$val[i]$改为$(\sum dp[son])+cost[i]$,递归到某条路终点的时候把$val[i]$改为$inf$就好了。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=500010;
const ll inf=1e15;
struct poi{ll sum, delta;}tree[maxn<<2];
struct tjm{int too, pre;}e[maxn<<1], e2[maxn<<1], e3[maxn<<1];
struct qaq{int x, y, cost, pos;}q[maxn];
ll dp[maxn];
int n, m, x, y, tot, tot2, tot3, tott, l[maxn], r[maxn], last[maxn], last2[maxn], last3[maxn];
inline void read(int &k)
{int f=1; k=0; char c=getchar();while(c<'0' || c>'9') c=='-' && (f=-1), c=getchar();while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();k*=f;
}
inline void add(int x, int y){e[++tot]=(tjm){y, last[x]}; last[x]=tot;}
inline void add2(int x, int y){e2[++tot2]=(tjm){y, last2[x]}; last2[x]=tot2;}
inline void add3(int x, int y){e3[++tot3]=(tjm){y, last3[x]}; last3[x]=tot3;}
inline void up(int x) {tree[x].sum=min(tree[x<<1].sum, tree[x<<1|1].sum);}
inline void addone(int x, int l, int r, ll delta)
{tree[x].delta=min(inf, tree[x].delta+delta);tree[x].sum=min(inf, tree[x].sum+delta);
}
inline void down(int x, int l, int r)
{int mid=(l+r)>>1;addone(x<<1, l, mid, tree[x].delta);addone(x<<1|1, mid+1, r, tree[x].delta);tree[x].delta=0;
}
void build(int x, int l, int r)
{if(l==r) {tree[x].sum=inf; return;}int mid=(l+r)>>1;build(x<<1, l, mid); build(x<<1|1, mid+1, r);up(x);
}
void update(int x, int l, int r, int cx, ll delta)
{if(l==r) {tree[x].sum=delta; return;}down(x, l, r);int mid=(l+r)>>1;if(cx<=mid) update(x<<1, l, mid, cx, delta);else update(x<<1|1, mid+1, r, cx, delta);up(x);
}
void change(int x, int l, int r, int cl, int cr, ll delta)
{if(cl>cr) return;if(cl<=l && r<=cr) {addone(x, l, r, delta); return;}down(x, l, r);int mid=(l+r)>>1;if(cl<=mid) change(x<<1, l, mid, cl, cr, delta);if(cr>mid) change(x<<1|1, mid+1, r, cl, cr, delta);up(x);
}
ll query(int x, int l, int r, int cl, int cr)
{if(cl>cr) return inf;if(cl<=l && r<=cr) return tree[x].sum;down(x, l, r);int mid=(l+r)>>1; ll ans=inf;if(cl<=mid) ans=query(x<<1, l, mid, cl, cr);if(cr>mid) ans=min(ans, query(x<<1|1, mid+1, r, cl, cr));return ans;
}
void dfs1(int x, int fa)
{l[x]=++tott;for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) dfs1(too, x);r[x]=tott;
}
inline int find(int x)
{int l=1, r=m+1;while(l<r){int mid=(l+r)>>1;if(q[mid].pos>=x) r=mid;else l=mid+1; }return l;
}
void dfs2(int x, int fa)
{ll sum=0;for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) dfs2(too, x), sum=min(inf, sum+dp[too]);if(x==1) {dp[1]=sum; return;}for(int i=last2[x];i;i=e2[i].pre) update(1, 1, m, e2[i].too, min(inf, q[e2[i].too].cost+sum));for(int i=last3[x];i;i=e3[i].pre) update(1, 1, m, e3[i].too, inf);for(int i=last[x], too;i;i=e[i].pre)if((too=e[i].too)!=fa) change(1, 1, m, find(l[too]), find(r[too]+1)-1, sum-dp[too]);dp[x]=query(1, 1, m, find(l[x]), find(r[x]+1)-1);
}
inline bool cmp(qaq a, qaq b){return a.pos<b.pos;}
int main()
{read(n); read(m); build(1, 1, m);for(int i=1;i<n;i++) read(x), read(y), add(x, y), add(y, x);dfs1(1, 0); for(int i=1;i<=m;i++) read(q[i].x), read(q[i].y), read(q[i].cost), q[i].pos=l[q[i].x];sort(q+1, q+1+m, cmp); q[m+1].pos=n+1;for(int i=1;i<=m;i++) add2(q[i].x, i), add3(q[i].y, i);dfs2(1, 0);if(dp[1]>=inf) return puts("-1"), 0;printf("%lld\n", dp[1]);
}

View Code

转载于:https://www.cnblogs.com/Sakits/p/8085598.html

Codeforces 671D. Roads in Yusland(树形DP+线段树)相关推荐

  1. CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换,清晰易懂)

    CodeForces - 1401 F Reverse and Swap(线段树, 区间翻转, 区间交换)   首先一共有四个操作,第一个和第四个都是线段树的基本操作,直接用线段树实现.      第 ...

  2. 旅游(树形dp求树的最大独立集)

    链接:https://ac.nowcoder.com/acm/problem/15748 来源:牛客网 题目描述 Cwbc和XHRlyb生活在s市,这天他们打算一起出去旅游. 旅行地图上有n个城市,它 ...

  3. hdu5489 Removed Interval dp+线段树优化

    现在看这题居然直接秒了...去年看的时候还以为神题.. 设以第i项为结尾的lis前缀为f[i],以第j项为结尾的lis后缀为g[i],如果求出f[i]和g[j],然后枚举i,快速找到最大的满足a[j] ...

  4. 树上子链(树形dp求树的直径)

    树上子链 题意: 给定一棵树 T ,树 T 上每个点都有一个权值. 定义一颗树的子链的大小为:这个子链上所有结点的权值和 . 请在树 T 中找出一条最大的子链并输出. 题解: 求树的直径,题目中存在负 ...

  5. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  6. CodeForces - 1527E Partition Game(dp+线段树)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数列,现在需要将其划分成 kkk 段,使得贡献和最小 对于每段区间 [l,r][l,r][l,r] 的贡献为,其中每个数字,其最后一次出现的位置 ...

  7. Codeforces Round #620 (Div. 2) F2. Animal Observation (hard version) dp + 线段树

    传送门 文章目录 题意: 思路: 题意: 比如下面这个图: 思路: 对于这个题,比较容易就能考虑到dpdpdp,设f[i][j]f[i][j]f[i][j]为到了第iii行,覆盖了[j,j+k−1][ ...

  8. CodeForces - 855B - Marvolo Gaunt's Ring(线段树 or DP)

    题目:CodeForces - 855B 题解: 1.用dp做的: dp[0][i]是前i个p*a[i]的最大值, dp[1][i]是在dp[0][i]的基础上加上q*a[i]的最大值,这样可以保证j ...

  9. Codeforces Round #699 (Div. 2) E.Sorting Books(贪心+DP / 线段树)超高质量题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 E - Sorting Books 一排书架上有 nnn 本书排成一排,每本书上有一个颜色 aia_i ...

最新文章

  1. python画网络关系 节点和边存在文件里_python复杂网络分析库NetworkX
  2. seaborn 教程_使用Seaborn进行数据可视化教程
  3. Visual Studio 2012中使用GitHub
  4. LeetCode 2079. 给植物浇水(前缀和)
  5. linux安装sz rz_超级好用的文件传输命令rz与sz
  6. 小程序开发时能否使用我们自定义的字体图标
  7. 折半查找的思想及源码_二分查找及对应的几道经典题目
  8. WebSocket使用80端口的方法
  9. 数据科学包16-matplotlib的三个实例
  10. java.lang.ClassNotFoundException: net.sf.json.JSONObject
  11. 《东周列国志》第一百回 鲁仲连不肯帝秦 信陵君窃符救赵
  12. 关于阿里云个人网站备案流程的介绍
  13. 你是去上大学,别让大学上了你
  14. 实验六201771010101 白玛次仁
  15. 计算机网络的基本概念和因特网的基本知识
  16. L1-016. 查验身份证
  17. MPLS基础概述MP-BGP实验(华为 DataCome)
  18. [编程题] 大富翁游戏(美团点评2017秋招)
  19. linux系统的监控工具名称,Linux下几款系统监控工具介绍
  20. HTML+CSS练习案例

热门文章

  1. java.lang.NoClassDefFoundError: org/springframework/dao/support/DaoSupport
  2. MaxCompute 2.0—从ODPS到MaxCompute
  3. iOS开发UI篇—iOS开发中三种简单的动画设置
  4. 英语听力里面的religion words
  5. severity distribution: tail of distributions
  6. 如果有机会,买一个能够兼容多终端的大屏幕是很重要的
  7. 外国人看来也喜欢拜年
  8. [Hive_add_11] Hive 使用 UDTF 实现日志降维
  9. 关于FlexBox的布局
  10. 作业1-四则运算题目生成程序