首页 > 其他分享 >[刷题笔记] Luogu P1612 [yLOI2018] 树上的链

[刷题笔记] Luogu P1612 [yLOI2018] 树上的链

时间:2024-07-01 16:54:02浏览次数:1  
标签:二分 cout int Luogu yLOI2018 dfs P1612 leq 节点

Problem

Description

Description

给定一棵有 \(n\) 个节点的树。每个节点有一个点权和一个参数。节点 \(i\) 的权值为 \(w_i\),参数为 \(c_i\)。\(1\) 是这棵树的根。

现在,对每个节点 \(u\)(\(1 \leq u \leq n\)),请在树上你找到最长的一条链 \(v_1, v_2, \dots v_m\),满足如下条件:

  1. \(v_1 = u\)。
  2. 对 \(2 \leq i \leq m\), 有 \(v_i\) 是 \(v_{i - 1}\) 的父节点。
  3. 链上节点的点权和不超过 \(c_u\),即 \(\sum_{j = 1}^m w_{v_j} \leq c_u\)。

对全部的测试点,保证 \(1 \leq u, v \leq n \leq 10^5\),\(1 \leq p_i \lt i\),\(1 \leq w_i \leq c_i \leq 10^9\)。

Analysis

一种暴力的方法是对于每个点向上 dfs,直接模拟即可。

实际上我们只需要一遍 dfs 即可解决问题。

注意到“链” 的定义:节点 \(u\) 向上走的路径叫做链。因此我们可以用一个栈动态维护链内元素。每次搜到时入栈,回溯时弹栈。

入栈的不一定是节点本身,也可以是节点的某种信息。本题中我们将每个节点的 \(w\) 到根节点的前缀和入栈。题目要求满足 \(\sum_{j = 1}^m w_{v_j} \leq c_u\) 的最大长度链,即最小化链头下标。容易发现可以二分解决。

令链头为 \(v\),链尾为 \(u\),即求 \(\min(v)\) 满足 \(a_u-a_v\le c_u\)。这个式子不好二分,我们移项得 \(a_v\ge a_u-c_u\)。对于 \(\forall u\),\(a_u-c_u\) 是定值。直接二分即可。

Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1000100;
int n;
vector <int> Edge[N],stk;
int w[N],c[N];
int ans[N];
void dfs(int u)
{
 //   cout<<u<<endl;
    stk.push_back(stk.back()+w[u]);
    int sum = 0 ;
    int l = 0 , r = stk.size() - 1;
    while(l <= r)
    {
      //  cout<<l<< " "<<r<<endl;
        int mid = (l+r) >> 1;
      //  cout<<mid<<endl;
        if(stk.back()-stk[mid] <= c[u] ) 
        {
            sum = mid;
            r = mid - 1;
        }
        else l = mid + 1;
    }
    ans[u] = stk.size() - sum - 1;
    for(auto v:Edge[u]) dfs(v);
    stk.pop_back();
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    for(int i=2;i<=n;i++)
    {
        int p;
        cin>>p;
        Edge[p].push_back(i);
    }  
    for(int i=1;i<=n;i++) cin>>w[i];
    for(int i=1;i<=n;i++) cin>>c[i];
    stk.push_back(0);
    dfs(1);  
    for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    cout<<endl;
    return 0;
}

标签:二分,cout,int,Luogu,yLOI2018,dfs,P1612,leq,节点
From: https://www.cnblogs.com/SXqwq/p/18278392

相关文章

  • [luoguP10608]双人游戏
    题目信息原题链接来源:[LGR-190]2024洛谷6月月赛IIDiv1T1/Div2T3题意长度为\(n\)的序列\(s\),其中只包含B,W和\(m\)个_。给定长度为\(m\)的序列\(O=[\langc_1,x_1\rang,\langc_2,x_2\rang,\cdots,\langc_m,x_m\rang](c_i\in\{\mathtt{R},\mathtt{M}\},s_{x_i}=\text{'_'......
  • [lnsyoj166/luoguP2822/NOIP2016提高组] 组合数问题
    题意原题链接给定\(n,m,k\),对于所有的\(0\lei\len,0\lej\lemin\{i,m\}\),有多少对\((i,j)\)满足\(k|(^i_j)\)sol在解决组合数问题时,若遇到\(n,m\le2000\)的情况,可以使用递推法(杨辉三角)来进行\(O(n^2)\)的预处理,再\(O(1)\)直接调用递推法求组合数\[(^n_m)=(^{n-1}_m)+(......
  • [lnsyoj284/luoguP2286/HNOI2004]宠物收养场
    题意原题链接每个宠物和领养人有一个对应的特点值\(a\),当领养人过多时,若添加一个特点值为\(a_p\)的宠物,则查询收养店中特点值最接近\(a_p\),为\(a_q\)的领养人(\(<a_p\)的值优先),将答案累加\(|a_q-a_p|\),然后删除该领养人,否则在收养店中添加一个领养人。反之亦然。求最终的答案\(......
  • [lnsyoj98/luoguP1403]约数研究
    题意原题链接求\(1\simn\)的约数个数和sol直接算很困难,考虑换一个角度求\(1\simn\)的约数个数和,等价于求\(1\simn\)分别是范围内几个数的约数对于第\(i\)个值,在\(1\simn\)中,存在\(i,2\cdoti,3\cdoti,\cdots,k\cdoti\),共\(\lfloor\frac{n}{i}\rfloor\)因此,最终......
  • [lnsyoj118/luoguP3369]普通平衡树
    题意维护一个数据结构,要求支持插入,删除,根据排名查数,根据数查排名,查询前驱,查询后继\(6\)个操作sol考虑到后四个查询的操作,会发现使用二叉搜索树(BST)完全可以实现为了完成这四个操作,需要在每个节点记录\(3\)个值:\(key\)表示当前节点的数\(cnt\)表示当前节点的数的个数(为了......
  • [DP] [倍增优化] Luogu P1081 [NOIP2012 提高组] 开车旅行
    [NOIP2012提高组]开车旅行题目描述小\(\text{A}\)和小\(\text{B}\)决定利用假期外出旅行,他们将想去的城市从$1$到\(n\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为\(h_i\),城市\(i\)和城市\(j\)之间的距......
  • Luogu P1784 数独 [ 模板 ] / P1074 靶形数独 题解 [ 蓝 ] [ 深搜 ] [ 剪枝 ] [ 卡常
    数独模板,靶形数独卡了2h,再也不想写数独了。思路显然是对每个格子进行枚举,类似八皇后的方法去做,朴素方法是由\((1,1)\)到\((9,9)\)遍历过去。优化我们人在做数独时,会优先选择已填格数多的行、列、区域,这样可以保证尝试次数少。同样,这一点在本题中也可以应用,但是有两......
  • [lnsyoj283/luoguP1856/IOI1998]矩形周长Picture
    题意原题链接求几个矩形的周长并sol遇到几何图形的**并,都可以使用扫描线思想来解决观察易得,与x轴平行的边和与y轴平行的边相互独立,因此可以扫描两次,分别计算并累加以与x轴平行的边为例:假设有一条平行于x轴的直线从下到上扫描,每当遇到一条边时,若这条边是某个矩形的下边,则在......
  • [DP] LCS例题 Luogu P1439 【模板】最长公共子序列 Luogu P4303 基因匹配
    LuoguP1439【模板】最长公共子序列【模板】最长公共子序列题目描述给出\(1,2,\ldots,n\)的两个排列\(P_1\)和\(P_2\),求它们的最长公共子序列。输入格式第一行是一个数\(n\)。接下来两行,每行为\(n\)个数,为自然数\(1,2,\ldots,n\)的一个排列。输出格式一个数,即......
  • Luogu P2036 [COCI2008-2009 #2] PERKET
    LuoguP2036[COCI2008-2009#2]PERKET#include<bits/stdc++.h>usingnamespacestd;intn,ans=1e9+5;//ans初始化值大于所有可用食材全部使用产生的总酸度和总苦度ints[15],b[15];voiddfs(inttot,intk,intl){//k为当前酸度,l为当前甜度if(to......