首页 > 其他分享 >CSP-S 2023 种树-题解

CSP-S 2023 种树-题解

时间:2023-10-23 17:11:08浏览次数:35  
标签:int 题解 Mid St Height Limit 2023 Now CSP

CSP-S 2023 种树-题解

闲话

Mark.Down看错题面了,我一直以为树是倒着长的。

题目描述

给定一棵树,每天可以选择一个与已种树的地块相连的地块种树,每棵树每天会长\(max(1,c_i\times x+b_i)\)米(\(x\)代表从任务开始第一天的天数),问最少多少天可以使\(\forall i\in n,Height_i\ge a_i\)。

题目分析

直接求解不好做,那我们可以考虑二分答案,求解转判定。

二分答案的单调性证明:可知每天树都会向上生长,所以只要在一个小的天数能完成任务,那么使用同样的策略可以直接种完然后等待即可,一定也是满足要求的。

那么我们考虑对答案进行判定,我们可以根据极限时间求出在当前极限时间下,每棵树最晚在那一天进行种植,对于每个有子节点的节点,他必须在子节点的种植极限时间之前种植,也就是说\(Limit_u=min(Limit_u-1,Limit_i)\),对于\(Limit\)的求解,我们也可以二分答案,看从那天开始生长直到限制时间能满足该棵树的要求。求解所有\(Limit\)之后,我们只需要将其排序,看能否有一个合法的序列完成种植即可,而不合法的情况则是在排序后出现\(Limit_i<i\)的情况,也就说明完全无法形成这样的一个序列。

优化

看起来上面的思路很美好,但是这个题需要卡常,一些奇怪的卡常点:1)如果当前节点不是根节点并且\(Limit\le 1\)那么可以直接返回,不需要排序了。2)把变量定义在外面。

Code

/*
 * @Author: Ehundategh
 * @Date: 2023-10-23 11:50:50
 * @FilePath: \Code\CSP-S\tree.cpp
 * @Description: You Steal,I kill
 */
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 100001
#define Min(a,b) if(a<b) b=a
using namespace std;
#define long_num __int128
int Head[MAXN],Total,n,In1,In2;
long long A[MAXN],B[MAXN],C[MAXN],LimitT[MAXN],EndT[MAXN],EndV[MAXN];/*max(B[i]+x*C[i],1)*/
template <class T>
void Read(T &x){
    x=0;
    bool f=false;
    char c=getchar();
    while(c<'0' or c>'9'){
        if(c=='-')f=true;
        c=getchar();
    }
    while('0'<=c and c<='9'){
        x=(x<<1)+(x<<3)+(c^48);
        c=getchar();
    }
    if(f)x=-x;
}
struct edge{
    int St,Ed,Next;
}Edge[MAXN<<1];
inline void Edge_Add(int St,int Ed){
    Edge[++Total]={St,Ed,Head[St]};
    Head[St]=Total;
}
long_num Height;
inline bool Check(int Now,int St,int Ed){
    Height=0;
    if(St>EndT[Now]){
        Height=Ed-St+1;
    }
    else if(St<=EndT[Now]&&Ed>=EndT[Now]){
        Height+=Ed-EndT[Now];
        Height+=((B[Now]+C[Now]*(long_num)St+EndV[Now])*(EndT[Now]-(long_num)St+1))>>1;
    }
    else{
        Height=((B[Now]+C[Now]*(long_num)St+B[Now]+C[Now]*(long_num)Ed)*(long_num)(Ed-St+1))>>1;
    }
    return Height>=A[Now];
}
inline int Tackle(int Now,int Limit){
    int L=1,R=Limit;
    while(L<R){
        int Mid=(L+R)>>1;
        if(Mid==L) Mid++;
        if(Check(Now,Mid,Limit)) L=Mid;
        else R=Mid-1;
    }
    return L;
}
inline void Take(int Now,int From,int Limit){
    LimitT[Now]=Tackle(Now,Limit);
    if(LimitT[Now]<=0||(Now!=1&&LimitT[Now]<=1)) return;
    for(int i=Head[Now];i;i=Edge[i].Next){
        int To=Edge[i].Ed;
        if(To==From) continue;
        Take(To,Now,Limit);
        Min(LimitT[To]-1,LimitT[Now]);
    }
    if(LimitT[Now]<=0||(Now!=1&&LimitT[Now]<=1)) return;
}
inline void Init(){
    for(int i=1;i<=n;i++){
        if(C[i]<0) EndT[i]=(B[i]-1)/-C[i],EndV[i]=(B[i]+EndT[i]*C[i]);
        else EndT[i]=1<<30;
    }
    return;
}
inline bool Judge(int Mid){
    Take(1,1,Mid);
    sort(LimitT+1,LimitT+n+1);
    for(int i=1;i<=n;i++){
        if(LimitT[i]<i) return false;
    }
    return true;
}
int main(){
    freopen("tree.in","r",stdin);
    freopen("tree.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) Read(A[i]),Read(B[i]),Read(C[i]);
    for(int i=1;i<n;i++){
        Read(In1);Read(In2);
        Edge_Add(In1,In2);
        Edge_Add(In2,In1);
    }
    Init();
    int L=1,R=1<<30;
    while(L<R){
        int Mid=(L+R)>>1;
        if(R==Mid) Mid--;
        if(Judge(Mid)) R=Mid;
        else L=Mid+1;
    }
    printf("%d",L);
    return 0;
}

标签:int,题解,Mid,St,Height,Limit,2023,Now,CSP
From: https://www.cnblogs.com/Ehundategh/p/17782940.html

相关文章

  • P8820(csp-s 2022 T4)题解
    背景:由于FZ考试因疫情取消,于是我们学校组织了线上测试。赛场连假做法都没打完,然后暴力忘记交了。。。题目链接参考博客题目评价:场切有点困难,但是76分比较容易。解法一眼\(ddp\),没话说。下面假设树以\(1\)为根。一次传输称作从一个点跳到另一个点。设询问的两个点为\(......
  • CSP-S2023 游记
    考的不算很好,本来是不想写下这篇的,但,毕竟是最后一个赛季,还是且行且珍惜吧。嗯……先放一首歌,随到了邓寓君的《青丝》,那就循环这首吧。赛前考前的几天有些茫然,总觉得相比一年前,自己好像没有什么与之相似的地方。如果让一年前的自己换了样貌站在我的面前,我能否通过平常交谈将其认......
  • 2023ICLR_SFNet: Selective frequency network for image restoration
    1.在运行SFNet代码时,前后代码保持不变,运行两次结果发生变化,把下面这段代码注掉就可以保持前后两次运行结果一致,不确定是否是nn.BatchNorm2d计算均值和方差导致classdynamic_filter(nn.Module):def__init__(self,inchannels,mode,kernel_size=3,stride=1,group=8)......
  • CSP-S 2023 游寄
    CSP-S2023游寄10.20星期五上午睡到十一点,收拾收拾去学校集合。下午上车,开摆。晚上到酒店,吃饭,搓牌,摆烂。10.21星期六晚上睡觉没关窗,感冒了(((上午复习,摆烂,睡觉。下午考试,带的食物和水一个半小时就全都消耗完了,口干舌燥。头疼还趴了一个小时。150+rand遗憾离场。比赛报......
  • [译]2023年 Web Component 现状
    本文为翻译原文地址:2023StateofWebComponents:Today'sstandardsandaglimpseintothefuture.最近,我写了关于如何构建你的第一个WebComponent,以及基本v1WebComponent规范的一些历史和解释。但是自从v1在2020年获得全面支持以来,WebComponent世界发生了更多的事......
  • 重磅|博睿数据 Bonree ONE 2023秋季版焕新发布!
    写文章重磅|博睿数据BonreeONE2023秋季版焕新发布!2023年10月20日,以「数智融,ONE向新」为主题的BonreeONE秋季产品发布会在深圳圆满落幕。此次发布会上,博睿数据隆重发布新一代一体化智能可观测平台——BonreeONE秋季正式版,重点升级数据采集、全局拓扑、数据分析、会话回放等多......
  • 题解合集
    CF1846:CF1846ACF1846BCF1846CCF1846DCF1846E......
  • CSP-S 2023 比赛报告
    CSP-S2023比赛报告开场看T1,发现很简单。快速写完,发现过不了样例2,调了半天,发现没有判和读入相同。然后去看T2,发现不会,直接\(O(n^2)\)跑路。T3一眼大模拟,放弃。16:00有点头疼,趴了一会。16:50醒了。T4想了想,发现可以直接贪。但是二分解方程调不出来,最后只能保证\(......
  • CF1839D题解
    分析啊这道题就做得很难受了……手玩一下样例,不难发现答案就是分出\(k\)段不是单调上升序列的序列,求这些序列的最小长度和。显然有状态\(f_{l,r,k}\)表示\([l,r]\)序列分成\(k\)段的最小长度和。转移很好想,即枚举\(x\),\(y\)分别表示左区间的右端点以及段数,空间复杂度\(\math......
  • 题解:【CF1888E】 Time Travel
    题目链接刚从modinte那里学到的广义dijkstra。注意到一定不会有路径形如\(x\toy\tox\),这样等价于\(x\)在原地等上两个时刻,我们记\(d_i\)表示到达\(i\)节点需要的最少时间。建图,边权为当前这一条边在哪一个历史时刻。然后用一个set来存下每个历史时刻在第几次时间......