9.2

P9755

题目

我们可以对最少天数进行二分答案

然后通过数学方法求出每个节点的最晚达到时间,记为 \(t[i]\)

然后采用贪心的思想,肯定要先去处理 \(t[i]\) 最大的节点

从该节点一直往上跳,直到遇到已经种过树的节点

当然路过的节点也都应该进行标记,后面碰到就不需要求了

注意进行数学计算时会超 \(long long\) 需要开 \(\_\_int128\)

这类题目还是很讲究细节的,写代码的时候全程不能分神啊

CODE
#include<bits/stdc++.h>
#define fst first
#define sec second
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef __int128 LL;
typedef pair<int,int> pii;
const int maxn=1e5+5;
const int inf=1e9+1;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
	x=(f ? -x : x);
}
void read(LL& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
	x=(f ? -x : x);
}
int head[maxn],nxt[maxn<<1],e[maxn<<1];
int mp_cnt;
int f[maxn];
pii t[maxn];
bool vis[maxn];
LL a[maxn],b[maxn],c[maxn],lim[maxn];//lim不取1的末尾
int n;
void init_mp(){
	memset(head,-1,sizeof(head));
	mp_cnt=-1;
}
void add_edge(int u,int v){
	e[++mp_cnt]=v;
	nxt[mp_cnt]=head[u];
	head[u]=mp_cnt;
}
void dfs(int u,int fa){
	f[u]=fa;
	for(int i=head[u];~i;i=nxt[i]){
		int v=e[i];
		if(v==fa) continue;
		dfs(v,u);
	}
}
LL cal(int id,int l,int r){
	if(l>lim[id]) return r-l+1;
	else if(r>lim[id]) return r-lim[id]+cal(id,l,lim[id]);
	else return (LL)(r-l+1)*b[id]+(LL)(l+r)*(r-l+1)*c[id]/2;
}
bool check(int p){
	for(int i=1;i<=n;i++){
		int l=1,r=p,ans=-1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(cal(i,mid,p)>=a[i]) ans=mid,l=mid+1;
			else r=mid-1;
		}
		if(ans<0) return false;
		t[i].fst=ans,t[i].sec=i;
		vis[i]=0;
	}
	sort(t+1,t+n+1);
	vis[1]=1;
	int d=1;
	for(int i=1;i<=n;i++){
		if(vis[t[i].sec]) continue;
		if(t[i].fst<d) return false;
		int u=t[i].sec;
		while(!vis[u]){
			++d;
			vis[u]=1;
			u=f[u];
		}
		if(t[i].fst<d) return false;
	}
	return true;
}
int main(){
	read(n);
	for(int i=1;i<=n;i++){
		read(a[i]),read(b[i]),read(c[i]);
		if(c[i]<0){
			if(b[i]%c[i]) lim[i]=-b[i]/c[i];
			else lim[i]=-b[i]/c[i]-1;
		}
		else lim[i]=inf;
	}
	init_mp();
	int u,v;
	for(int i=1;i<n;i++){
		read(u),read(v);
		add_edge(u,v),add_edge(v,u);
	}
	dfs(1,0);
	int l=n,r=inf,ans=0;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d",ans);
	return 0;
}
//^o^

P7914

贴个代码,今天马上结束了

CODE
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int mod=1e9+7;
const int maxn=505;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=(x<<3)+(x<<1)+c-48;
	x=(f ? -x : x);
}
LL dp[maxn][maxn][6];
//0:全是* 1:左右两个相互匹配的括号 2:左边括号,右边*
//3:左右两个不匹配的括号 4:左边*,右边括号 5:两边全是*
char c[maxn];
int n,k;
int main(){
	read(n),read(k);
	scanf("%s",c+1);
	for(int i=1;i<=n;i++) dp[i][i-1][0]=1;
	for(int len=1;len<=n;len++){
		for(int l=1,r=len;r<=n;l++,r++){
			if(len<=k) dp[l][r][0]=dp[l][r-1][0]&(c[r]=='?'||c[r]=='*');
			if(len>=2){
				for(int i=l;i<r;i++){
					if((c[l]=='?'||c[l]=='(')&&(c[r]=='?'||c[r]==')')){
						dp[l][r][1]=dp[l+1][r-1][0]+dp[l+1][r-1][2]+dp[l+1][r-1][3]+\
						dp[l+1][r-1][4];
						dp[l][r][1]%=mod;
					}
					dp[l][r][2]+=dp[l][i][3]*dp[i+1][r][0]%mod,dp[l][r][2]%=mod;
					dp[l][r][3]+=(dp[l][i][2]+dp[l][i][3])*dp[i+1][r][1]%mod;
					dp[l][r][4]+=(dp[l][i][4]+dp[l][i][5])*dp[i+1][r][1]%mod;
					dp[l][r][3]%=mod,dp[l][r][4]%=mod;
					dp[l][r][5]+=dp[l][i][4]*dp[i+1][r][0]%mod,dp[l][r][5]%=mod;
				}
			}
			dp[l][r][5]=(dp[l][r][5]+dp[l][r][0])%mod;
			dp[l][r][3]=(dp[l][r][3]+dp[l][r][1])%mod;
		}
	}
	printf("%lld",dp[1][n][3]);
	return 0;
}
//^o^
posted @ 2025-09-02 21:30  huangems  阅读(6)  评论(0)    收藏  举报