题意:给你一棵二叉树,点有点权,每次往左或者往右走,求最长走的路,并且点权和小于k;
思路:官方题解,尺取,我的写法,树上二分,
对于一条链,枚举每个点为终点,vector存该点到根节点的前缀和,二分一下即可;
详见代码;

借鉴下网友代码!
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstdio>
#include<cmath>
#include<string>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstring>
#include<vector>
#include<list>
#include<set>
#include<map>
using namespace std;
#define ll long long
#define pi (4*atan(1.0))
#define eps 1e-4
#define bug(x) cout<<"bug"<<x<<endl;
const int N=1e6+10,M=1e6+10,inf=2147483647;
const ll INF=1e18+10,mod=2147493647;
///数组大小
int n,ans,k,a[N];
vector<int>v;
void dfs(int x)
{
int s=0,t=v.size()-1;
int e=v.size()-1,ansq=-1;
while(s<=e)
{
int mid=(s+e)>>1;
if(v[t]-v[mid]<=k)
{
ansq=mid;
e=mid-1;
}
else s=mid+1;
}
if(v[t]<=k)ans=max(ans,t+1);
else ans=max(ans,t-ansq);
int z=v[v.size()-1];
if(x*2<=n)
{
v.push_back(z+a[x<<1]);
dfs(x<<1);
v.pop_back();
}
if(x*2+1<=n)
{
v.push_back(z+a[x<<1|1]);
dfs(x<<1|1);
v.pop_back();
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
ans=0;
v.clear();
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
v.push_back(a[1]);
dfs(1);
if(ans)printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
浙公网安备 33010602011771号