[九省联考2018]林克卡特树(DP+wqs二分)

对于k=0和k=1的点,可以直接求树的直径。

然后对于60分,有一个重要的转化:就是求在树中找出k+1条点不相交的链后的最大连续边权和。

这个DP就好。$O(nk^2)$

然后我们完全不可以想到,将best[k](选择k条链的答案)打表输出,更不可能然后作差分,发现得到的数组是递减的。

这说明:best[k]是一个上凸包。

于是我们可以二分一个斜率去切这个凸包(类似导数),根据切点横坐标与k的大小旋转直线(改变斜率)。

考虑给你一个直线斜率k,怎么找到它和凸包的切点。实际上就相当于将这个凸函数减去y=kx,再求凸包最高点。

感性理解一下,就是相当于在凸包下面画一条直线,然后旋转整个坐标系使这条直线就是x轴,然后正确性就比较显然了。

现在问题就是,如何找到最高点,这成了一个最优性问题,DP方程里可以去掉一维(已选链数不需要记录了)。

这样就可以通过了,复杂度$O(kn\log n)$

这个好像叫wqs二分,又叫凸优化,好像和BZOJ2654很像,但我没有看出十分相似的地方。

代码很短,但DP很难写

https://www.luogu.org/problemnew/solution/P4383

https://blog.csdn.net/izumi_hanako/article/details/80071419

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rep(i,l,r) for (int i=l; i<=r; i++)
 5 typedef long long ll;
 6 using namespace std;
 7
 8 const int N=300010;
 9 int n,k,u,v,w,cnt,to[N<<1],nxt[N<<1],val[N<<1],h[N];
10 ll mid,tot;
11 void add(int u,int v,int w){ to[++cnt]=v; val[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt; }
12 struct P{
13     ll x,y;
14     bool operator < (const P &b) const {return x==b.x? y>b.y : x<b.x;}
15     P operator + (const P &b) const {return (P){x+b.x,y+b.y};}
16     P operator + (int b) {return (P){x+b,y};}
17 }dp[3][N];
18 P upd(P a){ return (P){a.x-mid,a.y+1}; }
19
20 void dfs(int u,int fa){
21     dp[2][u]=max(dp[2][u],(P){-mid,1});
22     for (int i=h[u],v; i; i=nxt[i])
23         if ((v=to[i])!=fa){
24             dfs(v,u);
25             dp[2][u]=max(dp[2][u]+dp[0][v],upd(dp[1][u]+dp[1][v]+val[i]));
26             dp[1][u]=max(dp[1][u]+dp[0][v],dp[0][u]+dp[1][v]+val[i]);
27             dp[0][u]=dp[0][u]+dp[0][v];
28         }
29     dp[0][u]=max(dp[0][u],max(upd(dp[1][u]),dp[2][u]));
30 }
31
32 int main(){
33     freopen("lct.in","r",stdin);
34     freopen("lct.out","w",stdout);
35     scanf("%d%d",&n,&k); k++;
36     rep(i,2,n) scanf("%d%d%d",&u,&v,&w),tot+=abs(w),add(u,v,w),add(v,u,w);
37     ll L=-tot,R=tot;
38     while (L<=R){
39         mid=(L+R)>>1; memset(dp,0,sizeof(dp)); dfs(1,0);
40         if (dp[0][1].y<=k) R=mid-1; else L=mid+1;
41     }
42     memset(dp,0,sizeof(dp)); mid=L; dfs(1,0); printf("%lld\n",L*k+dp[0][1].x);
43     return 0;
44 }

原文地址:https://www.cnblogs.com/HocRiser/p/9055203.html

时间: 2024-08-27 10:37:49

[九省联考2018]林克卡特树(DP+wqs二分)的相关文章

[八省联考2018]林克卡特树

题目描述 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做"LCT" 的挑战,它的规则是这样子的:现在有一个N 个点的 树(Tree),每条边有一个整数边权vi ,若vi >= 0,表示走这条边会获得vi 的收益:若vi < 0 ,则表示走这条边需要支付- vi 的过路费.小L 需要控制主角Link 切掉(Cut)树上的 恰好K 条边,然后再连接 K

解题:八省联考2018 林克卡特树

题面 DP凸优化 题目并不难 先转化问题,显然k=0的时候我们都知道是求直径,然后k=1就是选两条点不相交的链拼起来,很容易推出题目就是要我们在树上选$k+1$条点不相交的链 事实上你直接按照边不相交做,取k+1次直径都可以得到50pts的好成绩,我佛了(不要问我怎么知道的 这个东西是可以DP的(稍微有点麻烦):设$dp[i][j][0/1/2]$表示以$i$为根的子树里选出j条链,这时i的度数为0/1/2的最优解.度数为零表示i是单独一个点,度数为1表示是链的端点,度数为2就是链中间的一个点

P4383 [八省联考2018]林克卡特树lct 树形DP+凸优化/带权二分

$ \color{#0066ff}{ 题目描述 }$ 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做"LCT" 的挑战,它的规则是这样子的:现在有一个N 个点的 树(Tree),每条边有一个整数边权vi ,若vi >= 0,表示走这条边会获得vi 的收益:若vi < 0 ,则表示走这条边需要支付- vi 的过路费.小L 需要控制主角Link 切掉(

[八省联考2018]林克卡特树lct

#include<bits/stdc++.h> #define RG register #define IL inline #define _ 500005 #define INF 1e18 #define ll long long using namespace std; IL ll gi(){ RG ll data = 0 , m = 1; RG char ch = 0; while(ch != '-' && (ch<'0' || ch > '9')) ch =

[luogu] P4364 [九省联考2018]IIIDX(贪心)

P4364 [九省联考2018]IIIDX 题目背景 Osu 听过没?那是Konano 最喜欢的一款音乐游戏,而他的梦想就是有一天自己也能做个独特酷炫的音乐游戏.现在,他在世界知名游戏公司KONMAI 内工作,离他的梦想也越来越近了. 这款音乐游戏内一般都包含了许多歌曲,歌曲越多,玩家越不易玩腻.同时,为了使玩家在游戏上氪更多的金钱花更多的时间,游戏一开始一般都不会将所有曲目公开,有些曲目你需要通关某首特定歌曲才会解锁,而且越晚解锁的曲目难度越高. 题目描述 这一天,Konano 接到了一个任务

【BZOJ5248】【九省联考2018】一双木棋(搜索,哈希)

[BZOJ5248][九省联考2018]一双木棋(搜索,哈希) 题面 BZOJ Description 菲菲和牛牛在一块n行m列的棋盘上下棋,菲菲执黑棋先手,牛牛执白棋后手.棋局开始时,棋盘上没有任何棋子, 两人轮流在格子上落子,直到填满棋盘时结束.落子的规则是:一个格子可以落子当且仅当这个格子内没有棋子且 这个格子的左侧及上方的所有格子内都有棋子. 棋盘的每个格子上,都写有两个非负整数,从上到下第i行中从左到右第j列的格子上的两个整数记作Aij.Bij.在 游戏结束后,菲菲和牛牛会分别计算自己

九省联考 2018 游记

Day0:乘火车到了上海.明天就是激动人心的比赛啦 深夜和室友看<我在七年后等你>.这真是一款不错的手游,让人印象深刻啊 Day1:迷迷糊糊到了学校.编程环境是Win7?不太习惯啊. T1:一眼状压dp题. T2:肯定可以建成一棵树,然后直接贪心?不对啊,T2不应该这么水啊(开始怀疑) T3:乍一看怎么一点思路没有啊. 8:40~11:10:持续思考T3中. 11:10:终于有思路了!如果直接NTT向上dp的话,因为链的情况复杂度会不对,所以似乎可以树剖!用线段树分治和NTT处理重链上的dp!

[loj 2478][luogu P4843]「九省联考 2018」林克卡特树

传送门 Description 小L 最近沉迷于塞尔达传说:荒野之息(The Legend of Zelda: Breath of The Wild)无法自拔,他尤其喜欢游戏中的迷你挑战. 游戏中有一个叫做"LCT" 的挑战,它的规则是这样子的:现在有一个N 个点的 树(Tree),每条边有一个整数边权vi ,若vi >= 0,表示走这条边会获得vi 的收益:若vi < 0 ,则表示走这条边需要支付- vi 的过路费.小L 需要控制主角Link 切掉(Cut)树上的 恰好K

[BZOJ5251][九省联考2018]劈配(网络流)

5251: [2018多省省队联测]劈配 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 33  Solved: 22[Submit][Status][Discuss] Description 一年一度的综艺节目<中国新代码>又开始了. Zayid从小就梦想成为一名程序员,他觉得这是一个展示自己的舞台,于是他毫不犹豫地报名了. 题目描述 轻车熟路的Zayid顺利地通过了海选,接下来的环节是导师盲选,这一阶段的规则是这样的: 总共n名参赛选手(编号