CSPS2023 T4 求 Hack
  • 板块学术版
  • 楼主x383494
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/10/29 09:54
  • 上次更新2023/11/2 10:57:47
查看原帖
CSPS2023 T4 求 Hack
747335
x383494楼主2023/10/29 09:54

RT,只有 95 pts,但我拍不出来哪写挂了

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <queue>
#include <random>
std::mt19937 rdna(0x383494);
#define UP(i,s,e) for(auto i=s; i!=e; ++i)
using ll = long long;
using i128 = __int128;
using ld = long double;
#define double ld
namespace m{ // }{{{
using std::cin; using std::cout;
decltype(cin) &operator>>(decltype(cin) &in, i128 &x){ long long xx; in >> xx; x = xx; return in; } decltype(cout) &operator<<(decltype(cout) &ou, i128 x){ long long xx = x; ou << xx; return ou; }
constexpr int N = 1e5;
int in;
struct Earth{ ll a, b, c; } eths[N];
std::vector<int> tos[N];
int reach[N], fa[N];
int vis[N];
namespace Fast_Check{/*{{{*/
ll get_grow_len(int pl, ll day){
    return eths[pl].b + eths[pl].c * day;
}
void prepare(int pl, int day){
    if(eths[pl].c == 0){
        reach[pl] = day + 1 - std::ceil(eths[pl].a * 1.0 / eths[pl].b);
        return;
    }
    //double cross = (1-eths[pl].b) / eths[pl].c;
    //if(cross == std::ceil(cross)) cross -= 0.5;
    //ll upper = std::ceil(cross), downer = std::floor(cross);
    //if(eths[pl].c > 0) downer--; else upper++;
    //upper++;
    if(eths[pl].c < 0){
        ll cross = eths[pl].c == 0 ? 0 : (1-eths[pl].b) / (eths[pl].c);
        ll upper = cross+1, downer = cross;
        if((day+1-upper) >= eths[pl].a){
            reach[pl] = day+1-(eths[pl].a);
        } else {
            double left = day >= upper ? 
                eths[pl].a - (day+1-upper) :
                eths[pl].a + (get_grow_len(pl, day+1) + get_grow_len(pl, downer)) * (double)(downer+1-(day+1)) / 2;
                ;
            double dx = 114514; // (b+c*cross + b+c*cross-dx*c) * (dx+1) / 2 >= a
            double aa = -eths[pl].c / 2.0;
            double bb = get_grow_len(pl, downer) - eths[pl].c / 2.0;
            double cc = get_grow_len(pl, downer) - left;
            dx = (-bb + std::sqrt((bb*bb-4*aa*cc))) / (2*aa);
            if(std::floor(dx+1e-3) != std::floor(dx-1e-3)) dx = std::round(dx);
            reach[pl] = downer - std::ceil(dx);
        }
    } else {
        double aa = -eths[pl].c / 2.0;
        double bb = get_grow_len(pl, day) - eths[pl].c / 2.0;
        double cc = get_grow_len(pl, day) - eths[pl].a;
        double dx = (-bb + std::sqrt((bb*bb-4*aa*cc))) / (2*aa);
        if(std::floor(dx+1e-3) != std::floor(dx-1e-3)) dx = std::round(dx);
        reach[pl] = std::floor(day - dx);
    }
}
}/*}}}*/
namespace Slow_Check{/*{{{*/
    double get_grow_len(int pl, double day){
        return eths[pl].b + eths[pl].c * day;
    }
    double get_grow_sum(int pl, int now, int day){
        double cross = (1-eths[pl].b) * 1.0 / (eths[pl].c);
        if(cross == std::floor(cross)) cross -= 0.5;
        if(eths[pl].c < 0){
            if(now > cross){
                return day + 1 - now; // [now, day+1)
            }
            return day + 1 - std::ceil(cross)
                + (get_grow_len(pl, now) + get_grow_len(pl, std::floor(cross))) * (std::floor(cross)+1-now) / 2.0;
        } else if(eths[pl].c == 0){
            return (day+1-now) * 1.0 * eths[pl].b;
        } else {
            if(now > cross){
                return (get_grow_len(pl, now) + get_grow_len(pl, day)) * (day+1-now) / 2.0;
            }
            return (get_grow_len(pl, std::ceil(cross)) + get_grow_len(pl, day)) * (day+1-std::ceil(cross)) / 2.0
                + std::floor(cross)+1-now;
        }
    }
    void prepare(int pl, int day){
        int l = 0, r = day+1; // [l, r)
        while(r-l>1){
            int mid = (l+r)/2;
            if(get_grow_sum(pl, mid, day) >= eths[pl].a){
                l = mid;
            } else {
                r = mid;
            }
        }
        reach[pl] = l;
    }
}/*}}}*/
struct Comp_by_reach{ bool operator()(int x, int y) const { return reach[x] < reach[y]; }};
struct Comp_by_far_reach{ bool operator()(int x, int y) const { return reach[x] > reach[y]; }};
std::vector<int> todo;
#if 1
bool check(int maxday){
    UP(i, 0, in) Fast_Check::prepare(i, maxday);
    //reach[0] = 1;
    std::sort(todo.begin(), todo.end(), Comp_by_reach());
    std::fill(vis, vis+in, 0);
    vis[0] = 0;
    int day = 0;
    for(int i:todo){
        //if(vis[i]) continue;
        for(int j=i; !vis[j]; j=fa[j]){
            vis[j] = 1;
            day++;
        }
        if(day > reach[i]) return false;
    }
    return true;
}
#else
std::priority_queue<int, std::vector<int>, Comp_by_reach> pq;
bool check(int maxday){
    pq = decltype(pq)();
    UP(i, 0, in) prepare(i, maxday);
    UP(i, 0, in) if((int)tos[i].size() == 1 && i != 0) pq.push(i);
    int day = in;
    std::fill(vis, vis+in, 0);
    while(!pq.empty()){
        int now = pq.top();
        pq.pop();
        if(reach[now] < day) return false;
        vis[fa[now]]++;
        if(vis[fa[now]] == (int)tos[fa[now]].size()-1){
            pq.push(fa[now]);
        }
        day--;
    }
    return true;
}
#endif
void mkfa(int x, int f){
    fa[x] = f;
    for(int i:tos[x]){
        if(i == f) continue;
        mkfa(i, x);
    }
}
void work(){
    cin >> in;
    UP(i, 0, in){
        cin >> eths[i].a >> eths[i].b >> eths[i].c;
        //if(eths[i].c == 0 && eths[i].b < 1) eths[i].b = 1;
    }
    UP(i, 1, in){
        int iu, iv; cin >> iu >> iv; iu--, iv--;
        tos[iu].push_back(iv);
        tos[iv].push_back(iu);
    }
    mkfa(0, 0);
    todo.reserve(in);
    UP(i, 0, in) todo.push_back(i);
    int l=in-1, r=1e9;
    while(r-l>1){
        int mid = (l+r)/2;
        if(check(mid)){ r=mid; }
        else { l = mid; }
    }
    cout << r;
}
} // {}}}
signed main(){m::work(); return 0;}
2023/10/29 09:54
加载中...