CSPS T4卡常求助
  • 板块学术版
  • 楼主Fasfree
  • 当前回复3
  • 已保存回复3
  • 发布时间2023/10/24 17:09
  • 上次更新2023/11/2 11:34:59
查看原帖
CSPS T4卡常求助
678318
Fasfree楼主2023/10/24 17:09

原代码(用了int128)

//
// Created by 32373 on 2023/10/24.
//

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#define md1 ((l+r) >> 1)
using namespace std;
typedef __int128 ll;
const long long N=1e5+3;

ll a[N], b[N], c[N];
ll ad[N];
struct p{
    vector<ll>ut;
};
struct nd{
	ll v, ps;
	bool operator < (const nd &b)const{
		return this->v < b.v;
	}
	bool operator > (const nd &b)const{
		return this->v > b.v;
	}
};
p ps[N];
ll dp[N], fa[N];

void dfs(ll nw, ll pr){
    fa[nw] = pr;
    dp[nw] = dp[pr] + 1;
    for (ll t:ps[nw].ut){
        if (t == pr)continue;
        dfs(t, nw);
    }
}

long long n;
ll eta[N]; // 每个点最晚种树天数 
void ck(ll d){ // 给定总天数,求每个点最晚的种树天数 
    for (ll x=1;x<=n;++x){
        ll l=1, r=d;
        while (l < r){
            ll mid=md1;
            if (c[x] >= 0) {
                ll st = b[x] + d * c[x];
                if (mid * st - (mid * (mid - 1)) / 2 * c[x] >= a[x]) {
                    r = mid;
                } else {
                    l = mid+1;
                }
            } else {
                ll cp= d - ceil((long double)b[x] / (long double)-c[x]) + 1;
                ll st=b[x] + (d-cp) * c[x];
                if (mid <= cp){
                    if (mid >= a[x]){
                        r = mid;
                    } else {
                        l = mid+1;
                    }
                } else {
                    ll val=cp;
                    val += (mid - cp) * st - (mid - cp) * (mid - cp - 1) / 2 * c[x];
                    if (val >= a[x]){
                    	r = mid;
                    } else {
                        l = mid+1;
                    }
                }

            }
        }
        eta[x] = d - l + 1;
    }

}
ll cnt2, mn;
bool iv=false;
ll up(ll p){ // 模拟种树 
	if (ad[p])return ad[p];
	if (p == 1){
		ad[p] = ++cnt2;
		return ad[p];
	}
	up(fa[p]);// 向上递归直到找到根节点或第一个已经种过的点 
	ll x=p;
	if (c[x] < 0){ // 检查求出来的最晚种树日期合不合法
		ll res, u1 = ceil((long double)b[x] / (long double)-c[x]);
		if (mn < u1){
			res = (mn) * (b[x] + c[x]) + (mn) * (mn-1) / 2 * c[x];
		} else {
			res = (u1-1) * (b[x] + c[x]) + (u1-1) * (u1-2) / 2 *c[x] + (mn - u1 + 1);
		}
		if (res < a[x]){
			iv = true; // 不合法 
		}
	} else {
		ll res = (mn) * (b[x] + c[x]) + (mn) *(mn-1) / 2 *c[x];
		if (res < a[x]){
			iv = true; // 不合法 
		}
	}
	ad[p] = ++cnt2; 
	return ad[p];
}
ll cnt;
struct pri{
	ll no, rd;
	bool operator < (const pri &b)const{
		return this->rd < b.rd;
	}
	bool operator > (const pri &b)const{
		return this->rd > b.rd;
	}
};

int main(){
    long long ta, tb, tc;
//    freopen("E:\\tree2.in", "r", stdin);
    scanf("%lld", &n);
    for (ll x=1;x<=n;++x){
        scanf("%lld %lld %lld", &ta, &tb, &tc);
        a[x] = ta, b[x] = tb, c[x] = tc;
    }
    for (ll x=1;x<n;++x){
        scanf("%lld %lld", &ta, &tb);
        ps[ta].ut.push_back(tb);
        ps[tb].ut.push_back(ta);
    }
    ll l=1, r=1e9;
//    ck(51);
//    puts("fuckccf");
    dfs(1, 0); // O(n)
	vector<pri>prs;
    while (l < r){  // 二分答案 
    	prs.clear();
    	mn = md1;
    	ck(md1); 	
    	for (ll x=1;x<=n;++x){ // O(n)
    		prs.push_back((pri){x, eta[x]});
    		ad[x] = 0;
		}
    	sort(prs.begin(), prs.end()); // O(nlogn)
    	cnt=0;
    	cnt2=0;
    	for (ll x=0;x<n;++x){ // O(n)
    		up(prs[x].no);
		}
		bool f=false;
    	for (ll x=1;x<=n;++x){
    		if (ad[x] > eta[x]){
    			f=true;
    			break;
			}
		}
		if (f or iv){
			l = md1+1;
			iv = false;
		} else {
			r = md1;
			iv = false;
		}
	}
	cout << (long long)l;
}

开了int128之后只能极限过前八个点(剩下全TLE)。

关int128多过了4个点,但同时出了一个WA,剩下全是多几十-一百多毫秒的TLE

这种应该怎么调,求各位大佬给个思路

2023/10/24 17:09
加载中...