社区讨论

求卡常

P9755[CSP-S 2023] 种树参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@mhizdj19
此快照首次捕获于
2025/11/03 18:11
4 个月前
此快照最后确认于
2025/11/03 18:11
4 个月前
查看原帖
我知道改二分边界能过。但是有没有其它的卡常方式qwq
90pts,TLE 的点都只有 1.07s。
CPP
#include<bits/stdc++.h>
#define int long long
#define ll __int128
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N=1e5+5;
int n,tot,fa[N],t[N],vis[N];
ll a[N],b[N],c[N];
vector<int>v[N];
void dfs(int x,int lst){
	fa[x]=lst;
	for(auto it:v[x])if(it!=lst)dfs(it,x);
	return;
}
inline int F(int x,int mid){
	int lt=0,rt=mid+1;
	while(lt+1<rt){
		ll md=lt+rt>>1,T;
		if(!c[x])T=b[x]*(mid-md+1);
		else if(c[x]>=0)T=b[x]*(mid-md+1)+c[x]*(md+mid)*(mid-md+1)/2;
		else{
			int tx=b[x],ty=-c[x];
			int num=(tx+ty-1)/ty;
			if(md>=num)T=mid-md+1;
			else if(mid<num)T=b[x]*(mid-md+1)+c[x]*(md+mid)*(mid-md+1)/2;
			else T=b[x]*(num-md)+c[x]*(md+num-1)*(num-md)/2+(mid-num+1);
		}
		if(T>=a[x])lt=md;
		else rt=md;
	}
	return lt;
}
bool check(int mid){
	for(int i=2;i<=n;i++){
		t[i]=F(i,mid);
		if(t[i]<=1)return 0;
	}
	vector<pii>v;
	for(int i=2;i<=n;i++)v.push_back({t[i],i});
	sort(v.begin(),v.end()),tot=1;
	memset(vis,0,sizeof(vis)),vis[1]=1;
	for(int i=0;i<v.size();i++){
		int tmp=0,now=v[i].se;
		while(!vis[now])tmp++,vis[now]=1,now=fa[now];
		if(tot+tmp>v[i].fi)return 0;
		tot+=tmp;
	}
	return 1;
} 
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
void write(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');return;
}
signed main(){
	// freopen("tree.in","r",stdin);
	n=read();
	for(int i=1;i<=n;i++)a[i]=read(),b[i]=read(),c[i]=read();
	for(int i=1,x,y;i<n;i++){
		x=read(),y=read();
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);
	int lt=0,rt=1e9+1;
	while(lt+1<rt){
		int mid=lt+rt>>1;
		if(check(mid))rt=mid;
		else lt=mid;
	}
	write(rt);
	return 0;
}
祝回复的人 rp++。

回复

3 条回复,欢迎继续交流。

正在加载回复...