首页 > 其他分享 >[CSP-S 2023] 种树

[CSP-S 2023] 种树

时间:2024-05-21 20:51:32浏览次数:17  
标签:return int 2023 mid long zero 种树 ans CSP

 

 

#include<bits/stdc++.h>
#define ll long long
#define pb push_back
#define mxn 100003
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
int n,p[mxn],d[mxn],ct[mxn];
ll a[mxn],b[mxn],c[mxn];
vector<int>g[mxn];
bool v[mxn];
inline __int128 get(ll i,ll n,__int128 a,__int128 b)
//从第1天到第N天,按 
{
    if(a<0){
        ll d=min((b-a-1)/(-a),(__int128)n+1);
        if(d<=i)return n-i+1;
        return n-d+1+(d-i)*b+(d-1+i)*(d-i)/2*a;
    }
    return (n+i)*(n-i+1)/2*a+b*(n-i+1);
}
void dfs(int x,int fa)
{
	for(int i:g[x])
	   if(i!=fa)
	   {
		        dfs(i,x);
		        p[x]=min(p[x],p[i]-1);
	   }   
} 
bool check(int mx)
{
    rep(i,1,n)
    //算出每棵树,最晚应该在哪个时间点来种 
	{
        if(a[i]>get(1,mx,c[i],b[i]))
		    return 0;
        int l=1,r=n;
        while(l<r)
		{
            int mid=(l+r+1)>>1;
            if(a[i]<=get(mid,mx,c[i],b[i]))
			    l=mid;
            else 
			    r=mid-1;
        }
        if(i==1)
		   l=1;
        p[i]=l;
    }
    dfs(1,0);  //修正每个点最晚的种树时间 
    rep(i,1,n)
	   ct[i]=0;
    rep(i,1,n)
	{
    	if(p[i]<1)
		    return 0;
    	ct[p[i]]++; //在第p[i]个时间要种树的行为,要执行多少次 
	}
	rep(i,1,n)
	//枚举时间 
	{
		ct[i]+=ct[i-1];  //统计一共要种多少棵树 
		if(ct[i]>i) //前i个时间只能种i棵树 
		   return 0;
	}
    return 1;
}
signed main(){
    scanf("%d",&n);
    rep(i,1,n)scanf("%lld%lld%lld",&a[i],&b[i],&c[i]);
    for(int i=1,x,y;i<n;++i)
	{
        scanf("%d%d",&x,&y);
        g[x].pb(y),g[y].pb(x);
    }
    int l=n,r=1e9;
    while(l<r)
	{
        int mid=(l+r)>>1;
        if(check(mid))r=mid;
        else l=mid+1;
    }
    cout<<l;
    return 0;
}

  

 

 

 

 

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
using namespace std;

const int N = 1e5, E = N << 1;
const long long Max = 1e9;

typedef pair<long long, int> pir;

int n;
long long a[N + 5], b[N + 5], c[N + 5], zero[N + 5];

int head[N + 5], to[E + 5], nxt[E + 5], tot = 1;
void add_edge(int u, int v)
{
	tot++;
	to[tot] = v;
	nxt[tot] = head[u];
	head[u] = tot;
	return ;
}
void add(int u, int v)
{
	add_edge(u, v);
	add_edge(v, u);
	return ;
}

long long d[N + 5];//limit
int sz[N + 5];

void calc_d(int u, long long ans)
{
	long long l = 1, r = n;
	d[u] = -1ll;
	while (l <= r)
	{
		long long mid = (l + r) >> 1;
		__int128 sum = 0, one = 1;

		if (c[u] >= 0)
			sum = one * (ans - mid + 1) * b[u]
				 + one * (mid + ans) * (ans - mid + 1) / 2 * c[u];
		else
		{
			if (mid > zero[u])
				sum = ans - mid + 1;
			else if (ans > zero[u])
				sum = one * (zero[u] - mid + 1) * b[u]
					 + one * (mid + zero[u]) * (zero[u] - mid + 1) / 2 * c[u]
					 + ans - zero[u];
			else
				sum = one * (ans - mid + 1) * b[u]
					 + one * (mid + ans) * (ans - mid + 1) / 2 * c[u];
		}

		if (one * a[u] <= sum)
		{
			d[u] = mid;
			l = mid + 1;
		}
		else
			r = mid - 1;
	}
	return ;
}

int fa[N + 5], in[N + 5];
void dfs(int u, int father)
{
	fa[u] = father;
	in[father]++;
	for (int i = head[u]; i; i = nxt[i])
	{
		int v = to[i];
		if (v == father)
			continue;
		dfs(v, u);
	}
	return ;
}

priority_queue<pir> q;
int seq[N + 5];
bool check(long long ans)
{
	for (int i = 1; i <= n; i++)
	{
		calc_d(i, ans);
		if (d[i] < 0)
			return false;
	}

	dfs(1, 0);
	for (int i = 1; i <= n; i++)
	{
		if (in[i] == 0)
			q.emplace(d[i], i);
	}

	for (int T = n; T > 0; T--)
	{
		int u = q.top().second;
		q.pop();
		seq[T] = u;

		if (fa[u])
		{
			in[fa[u]]--;
			if (in[fa[u]] == 0)
				q.emplace(d[fa[u]], fa[u]);
		}
	}

	for (int i = 1; i <= n; i++)
	{
		if (1ll * i > d[seq[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++)
	{
		scanf("%lld%lld%lld", a + i, b + i, c + i);
		if (c[i] < 0)
			zero[i] = (1ll - b[i]) / c[i];
	}
	for (int i = 1, u, v; i < n; i++)
	{
		scanf("%d%d", &u, &v);
		add(u, v);
	}

	long long l = 1, r = Max, ans = 0;
	while (l <= r)
	{
		long long mid = (l + r) >> 1;
		if (check(mid))
		{
			ans = mid;
			r = mid - 1;
		}
		else
			l = mid + 1;
	}
	printf("%lld\n", ans);
	return 0;
}

  

标签:return,int,2023,mid,long,zero,种树,ans,CSP
From: https://www.cnblogs.com/cutemush/p/18204903

相关文章

  • CSP历年复赛题-P1049 [NOIP2001 普及组] 装箱问题
    原题链接:https://www.luogu.com.cn/problem/P1049题意解读:装尽可能多的物品,使得总体积越大越好,即剩余空间最小,还是一个01背包问题,物品的体积就是其价值。解题思路:01背包模版题,物品体积、价值相同,直接采用一维dp。100分代码:#include<bits/stdc++.h>usingnamespacestd;co......
  • CSP历年复赛题-P1035 [NOIP2002 普及组] 级数求和
    原题链接:https://www.luogu.com.cn/problem/P1035题意解读:根据公式模拟法求解即可。解题思路:枚举i,计算sum,如果sum>k,则输出i100分代码:#include<bits/stdc++.h>usingnamespacestd;intmain(){intk;cin>>k;doublesum=0;inti=0;while(......
  • CSP历年复赛题-P1036 [NOIP2002 普及组] 选数
    原题链接:https://www.luogu.com.cn/problem/P1036题意解读:题目即要在n个数中,枚举出所有的子集,当子集中数字个数刚好为k时,求和,判断是否是素数。解题思路:方法一:二进制法通过二进制法,可以枚举一个集合中所有元素“选”或者“不选”的情况,用二进制1表示选该元素,二进制0表示不选。......
  • CSP历年复赛题-P1030 [NOIP2001 普及组] 求先序排列
    原题链接:https://www.luogu.com.cn/problem/P1030题意解读:已知中序、后序,求先序。解题思路:与洛谷题单指南-二叉树-P1827[USACO3.4]美国血统AmericanHeritage非常类似,不在介绍过程,直接给出代码。100分代码:#include<bits/stdc++.h>usingnamespacestd;stringin,post......
  • CSP历年复赛题-P1023 [NOIP2000 普及组] 税收与补贴问题
    原题链接:https://www.luogu.com.cn/problem/P1023题意解读:给定商品单价和对应销量表,计算使得采用预期价格销售得到最大利润时的最小补贴或者税收。解题思路:1、样例模拟31281303012031110-1-115政府预期价格:31商品成本:28,按成本价售卖销量:130商品单价:30,对应销量:120......
  • CSP历年复赛题-P1028 [NOIP2001 普及组] 数的计算
    原题链接:https://www.luogu.com.cn/problem/P1028题意解读:给定n,构造数列,可以用递归或者递推。解题思路:1、递归定义count(n)返回数列的个数  n==1时,count(n)=1  n!=1时,count(n)=1+count(1)+count(2)+...+count(n/2)注意,递归会导致大量重复计算,需要用一个hash......
  • CSP历年复赛题-P1029 [NOIP2001 普及组] 最大公约数和最小公倍数问题
    原题链接:https://www.luogu.com.cn/problem/P1029题意解读:已知x,y,求有多少对p、q,使得p、q的最大公约数为x,最小公倍数为y。解题思路:枚举法即可。枚举的对象:枚举p,且p必须是x的倍数,还有p<=yq的计算:q=x*y/p,q要存在,必须x*y%p==0,且gcd(p,q)==x100分代码:#include......
  • CSP历年复赛题-P1022 [NOIP2000 普及组] 计算器的改良
    原题链接:https://www.luogu.com.cn/problem/P1022题意解读:求解一元一次方程。解题思路:直接采用模拟法,对字符串进行解析设x保存未知数字母设lx保存"="左边的未知数系数,多个系数要累加设l保存"="左边的整数,多个整数要累加设rx保存"="右边的未知数系数,多个系数要累加设r保存"......
  • CSP历年复赛题-P1016 [NOIP1999 提高组] 旅行家的预算
    原题链接:https://www.luogu.com.cn/problem/P1016题意解读:用最少的加油费用到达另一个城市,中间有若干加油点,起点也可加油。解题思路:本题是一个贪心策略题:枚举每一个加油点i:1、初始加油点是起点2、汽车能跑的最大距离范围内,找到下一个更便宜的加油点的位置3、如果能找到更便......
  • CMU_15445数据库课程2023Fall
    这一个Project是让我们了解C++的语法以及改数据库项目的整体框架,基本的锁的使用,怎么Debug.一些零碎的知识碎片我放到最后了,以前是写C的,C++的很多语法还不是很熟悉,很多新的语法更不知道该怎么用.这次作业完成也是受益良多.Copy_on_Write字典树首先必须明确一个概念,......