Qiuly @ 2019-05-12 10:47:04
RT,无论是在
二分的地方自认为很迷,但是不知道应该怎么改才好......尝试过重构但未果。
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=6e5+2;
const ll inf=1e18+9;
int n,k,head[N],cnt;
struct date {
ll x;int y;
bool operator < (const date&var) const {return x==var.x?y>var.y:x<var.x;}
date operator + (const date&var) {return (date){x+var.x,y+var.y};}
date operator + (const ll&var) {return (date){x+var,y};}
}dp[3][N];
ll number(date var) {return var.x;}
struct Edge{int nxt,to,val;} G[N<<1];
void add(int u,int v,int w) {
G[++cnt]=(Edge){head[u],v,w},head[u]=cnt;
G[++cnt]=(Edge){head[v],u,w},head[v]=cnt;
}
template <typename _Tp> inline void IN(_Tp&x) {
char ch;bool flag=0;x=0;
while(ch=getchar(),!isdigit(ch)) if(ch=='-') flag=1;
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
if(flag) x=-x;
}
void check(ll add,int u,int fa) {
dp[0][u]=(date){0,0},
dp[1][u]=(date){-inf,0},
dp[2][u]=(date){add,1};
for(int e=head[u];e;e=G[e].nxt) {
int v=G[e].to;
ll w=G[e].val;
if(v==fa) continue;
check(add,v,u);
date num=max(dp[0][v],max(dp[1][v],dp[2][v]));
dp[2][u]=max(dp[2][u],dp[2][u]+num);
dp[2][u]=max(dp[2][u],dp[1][u]+(date){w,0}+max(dp[0][v],dp[1][v]+(date){-add,-1}));
dp[1][u]=max(dp[1][u],dp[1][u]+num);
dp[1][u]=max(dp[1][u],dp[0][u]+(date){w,0}+max(dp[1][v],dp[0][v]+(date){add,1}));
dp[0][u]=dp[0][u]+num;
}return;
}
ll wqs(ll sum) {
ll l=-sum,r=sum,mid;
date now;
while(l<r) {
mid=(l+r+1)>>1,check(mid,1,0);
now=max(dp[0][1],max(dp[1][1],dp[2][1]));
if(!(now.y^k)) {l=r=mid;break;}
now.y<k?l=mid:r=mid-1;
}
check(l,1,0);
now=max(dp[0][1],max(dp[1][1],dp[2][1]));
return now.x-1ll*mid*k;
}
int main() {
// freopen("lct2.in","r",stdin);
// freopen("P4383.out","w",stdout);
IN(n),IN(k);++k;
ll sum=0;
for(int i=1;i<n;++i) {
int x,y,v;IN(x),IN(y),IN(v);
add(x,y,v),sum+=abs(v);
}
printf("%lld\n",wqs(sum));
return 0;
}
by w4p3r @ 2019-08-13 16:06:01
return now.x-1ll*mid*k;
改成
return now.x-1ll*mid*now.y;
我才不会告诉你我也错在这儿
by Treaker @ 2020-06-18 19:43:02
@WAPER420 这是为啥呀。。。
by w4p3r @ 2020-06-18 20:00:53
@Treaker 我这都多久回答的了。。早忘了qaq
by Treaker @ 2020-06-18 20:05:45
@WAPER420 想想呗
by tommy0221 @ 2020-07-27 18:24:13
@Treaker 这个问题比较显然,建议重新看看您学wqs二分的那博客,如果找到的文章不那么差都会讲这个问题
by 5ab_juruo @ 2023-03-04 16:52:42
@WAPER4EVER 我按照你的方法改了被 LOJ 数据叉了。
by w4p3r @ 2023-03-04 18:05:22
@5ab_juruo 我的天哪。三年了还回复啊。我高一做的题这会儿都大一了。
马上我看一下吧。
by w4p3r @ 2023-03-04 18:25:43
@5ab_juruo 首先,我三年前讲错了,输出的答案就应该是
其次,注意你的二分要与你在值相同时求边数最小/边数最大要保持一致。
例如我的二分是这样的:
ll l=-inf,r=inf,ans=0;
while(l<=r)
{
ll mid=(l+r)>>1;
if(check(mid)<=k){ans=mid;r=mid-1;}
else l=mid+1;
}
那么这样的话在值相同时我应该求边数最小的方案。
但是我在原代码里求了边数最大的方案,所以导致了将
如果你 AC 了该题却被 hack 掉了,注意一下我上面说的这个问题。
by w4p3r @ 2023-03-04 18:26:45
哎呀好像甚至不是高一做的,初三做的。。
by CarroT1212 @ 2023-12-26 15:39:02
@WAPER4EVER 之前一直没搞懂为什么 wqs 有时候按最小有时候按最大的,帮大忙了,感谢
这会您都大二了吧