CF1714G 题解
__vector__ · · 题解
题外话:
感谢这道题把我送到了 1606th,并助我上了 pupil。
题意
定义
从
求
做法
既然需要用到总和,那么记录一下前缀和就行了。
显然,前缀和数组是递增的,也就是说,将对于每个点
至于怎么求,dfs 到一个点的时候,就顺便记录从
不过直接这么递推,记录的不是同一条路径上的前缀和。
处理方法(或者说具体实现)是,维护一个
剩余的看代码注释吧。
Code
#include <bits/stdc++.h>
using namespace std;
namespace Main
{
typedef long long ll;
const int maxn=2e5+5;
int t;
int head[maxn];
struct EDGE
{
int to,nxt,a,b;
}edge[maxn<<1];
int cnt;
inline void add(int u,int to,int a,int b)
{
edge[++cnt].to=to;
edge[cnt].a=a;
edge[cnt].b=b;
edge[cnt].nxt=head[u];
head[u]=cnt;
}
int n;
ll qzh[maxn];
int top;
ll qzh2[maxn];
int r[maxn];
void dfs(int u,int giva,int givb,int _fa)
{
top++;//当前路径的前缀和数组增加一个元素
qzh[top]=qzh[top-1]+(ll)giva;//记录 1---->u 的 a 前缀和
qzh2[top]=qzh2[top-1]+(ll)givb;//记录 1----->u 的 b 前缀和
int pos=upper_bound(qzh2+1,qzh2+top+1,qzh[top])-qzh2;
//二分求出第一个 b 前缀和大于 1---->u 的 a 前缀和的点(第一个不符合要求的点)
//这个点在路径上的编号减去 1 就是最后一个符合要求的点。
if(pos==top+1)
{//如果所有的点都符合要求,那就输出这条路径点的总量-1,就是 1----> u 的边的数量
r[u]=top-1;
}
if(pos!=top+1)
{//如果不是所有的点都符合要求
r[u]=pos-2;//pos-1是最后一个符合要求的点,而 1---->(pos-1),有 pos-2 条边。
}
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==_fa)continue;
dfs(to,edge[i].a,edge[i].b,u);
}
top--;//退出当前点,当前路径不再包含该点
}
void main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
int p,a,b;
scanf("%d%d%d",&p,&a,&b);
add(i,p,a,b);
add(p,i,a,b);
}
dfs(1,0,0,0);
for(int i=2;i<=n;i++)
{
printf("%d ",r[i]);
}
printf("\n");
//清空数据
cnt=0;
for(int i=0;i<=n;i++)
{
head[i]=0;
}
}
}
}
int main()
{
Main::main();
return 0;
}