帮帮忙,95WA#15
查看原帖
帮帮忙,95WA#15
792584
yuanzhiteng楼主2023/10/30 22:56

之前的帖子说是二分写挂了,但是我真的调不出来。

数据点 1515 与答案相差 11。

代码写了注释的。

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
#define ll __int128_t
const int maxn = 2e5 + 5;
const int maxday = 1e9 + 5;

template <typename T>
inline void read(T& x){
x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -f; c = getchar();}
while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();} x *= f;
}
template <typename T,typename... Args>
inline void read(T &x,Args&... Arg){read(x),read(Arg...);}

int n;
ll a[maxn],b[maxn],c[maxn];
int head[maxn],cnt;
struct Edge{
    int to,next;
}e[maxn << 1];
inline void add(int u,int v){
    e[++cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt;
}
ll one[maxn];                              //one[i]:第i块地最早第多少天开始只会增高1m
inline ll Ceil(ll x,ll y){
    if(x % y == 0)  return x / y;
    return x / y + 1;
}
inline void init(){                         //预处理one
    for(int i=1;i<=n;i++){
        if(c[i] > 0)    one[i] = -2;
        else if(c[i] == 0)  one[i] = -3;    //两种特殊情况打上不同的标记
        else one[i] = Ceil(b[i] - 1,-c[i]);
    }
}
ll deadline[maxn];                          //deadline[i]:第i块地最晚只能在第多少天种下才行
inline void dfs(int u,int fa){
    for(int i=head[u];i;i=e[i].next){
        int v = e[i].to;
        if(v == fa) continue;
        dfs(v,u);
        deadline[u] = min(deadline[u],deadline[v] - 1);
    }
}
inline bool check(int day){                 //分类讨论即可
    for(int i=1;i<=n;i++){
        if(one[i] == -3){
            deadline[i] = day + 1 - Ceil(a[i],b[i]);
            if(deadline[i] <= 0)    return 0;
        }
        else if(one[i] == -2){
            ll l = 1,r = day,mid;
            deadline[i] = 0;
            while(l <= r){
                mid = (l + r) >> 1;
                ll num = ((mid + day) * (day - mid + 1) / 2) * c[i] + (day - mid + 1) * b[i];
                if(num >= a[i]) deadline[i] = mid,l = mid + 1;
                else    r = mid - 1;
            }
            if(!deadline[i])   return 0;
        }
        else{
            if(day - one[i] + 1 >= a[i])  deadline[i] = day + 1 - a[i];
            else{
                ll need = a[i] - (day - one[i] + 1);
                deadline[i] = 0;
                ll l = 1,r = one[i] - 1,mid;
                while(l <= r){
                    mid = (l + r) >> 1;
                    ll num = ((mid + one[i] - 1) * (one[i] - mid) / 2) * c[i] + (one[i] - mid) * b[i];
                    if(num >= need) deadline[i] = mid,l = mid + 1;
                    else r = mid - 1;
                }
                if(!deadline[i])    return 0;    
            }    
        }
    }
    dfs(1,1);
    sort(deadline + 1,deadline + 1 + n);    //按顺序填充
    for(int i=1;i<=n;i++)   if(i > deadline[i])  return 0;
    return 1;
}
int main(){

    //freopen("tree15.in","r",stdin);

    read(n);
    for(int i=1;i<=n;i++)   read(a[i],b[i],c[i]);
    for(int i=1;i<n;i++){
        int u,v;
        read(u,v);
        add(u,v);
        add(v,u);
    }
    init();
    int l = n,r = maxday,mid;               //二分答案
    int ans = 0;
    while(l <= r){
        mid = (l + r) >> 1;
        if(check(mid))  r = mid - 1,ans = mid;
        else    l = mid + 1;
    }
    printf("%d\n",ans);

    return 0;
}
2023/10/30 22:56
加载中...