2023 ICPC 网络预选赛补题 II

2023 ICPC 网络预选赛 II

赛时 AC 题目

M. Dirty Work

点击查看代码
#include<bits/stdc++.h>
#define ld double
using namespace std;
const int maxn=1e6+5;
int a[maxn],b[maxn];
ld p[maxn],c[maxn];
int t,n;
bool cmp(ld a,ld b)
{
	return a<b;
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		scanf("%d%d",&a[i],&b[i]),
		cin>>p[i],
		c[i]=1.0*(a[i]+b[i])*p[i]+1.0*a[i]*(1.0-p[i]);
		sort(c+1,c+n+1);
		for(int i=1;i<=n;i++)
			c[i]+=c[i-1];
		ld ans=0;
		for(int i=1;i<=n;i++)
		ans+=c[i];
		printf("%.12lf\n",ans);	
	}
	return 0;
}

D. Project Manhattan

点击查看代码
/*
1. 突破点:按行(或列)遍历,则每行(或列)至少选一个人。
2. 易错点:每行(或列)不是只能选一个人(这个人满足其pay为该行或列的最小值),所有的负 pay 无论是否为最小值均应被统计入答案。
*/
#include <iostream>
#define ll long long
using namespace std;
const int maxn=510;
int mi[2][maxn];
int a[maxn][maxn]; ll ans,ansi;
int n,t;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		ans=0,ansi=0;
		for(int i=1;i<=n;i++)
		{
			mi[0][i]=1e6+1;
			for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]),
			mi[0][i]=min(mi[0][i],a[i][j]);
		}
		for(int j=1;j<=n;j++)
		{
			mi[1][j]=1e6+1;
			for(int i=1;i<=n;i++)
			mi[1][j]=min(mi[1][j],a[i][j]);
		}
		for(int i=1;i<=n;i++)
		{
			bool flag=false;
			for(int j=1;j<=n;j++)
				if(a[i][j]<0)
				{
					if(a[i][j]==mi[0][i])
					{
						if(flag) ans+=a[i][j];
						else flag=true;
					} 
					else ans+=a[i][j];
				}
			ans+=mi[0][i];	
		}
		for(int j=1;j<=n;j++)
		{
			bool flag=false;
			for(int i=1;i<=n;i++)
				if(a[i][j]<0)
				{
					if(a[i][j]==mi[1][j])
					{
						if(flag) ansi+=a[i][j];
						else flag=true;
					} 
					else ansi+=a[i][j];
				}
			ansi+=mi[1][j];
		}
		printf("%lld\n",min(ans,ansi));
	}
	return 0;
}

E. Another Bus Route Problem

点击查看代码
/*
1. 正解:以根节点 1 为起点跑 BFS。
2. 突破点:发现结论——若节点 i 被访问过,则从根节点 1 到 i 的树链上所有的节点一定已被访问过。
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
struct edge
{
	int v,next;
}e[maxn<<1];
int cnt,head[maxn];
void add(int u,int v)
{
	e[++cnt]=(edge){v,head[u]};
	head[u]=cnt;
}
int n,m,anc[maxn][25];
vector<int> gop[maxn];
void dfs(int u,int fa)
{
	anc[u][0]=fa;
	int v;
	for(int i=head[u];i;i=e[i].next)
	{
		v=e[i].v;
		if(v==fa) continue;
		dfs(v,u);
	}
}
bool vis[maxn];
queue<int> q;
int dis[maxn];
void bfs()
{
	vis[0]=true;
	q.push(1),vis[1]=true;
	dis[1]=0;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		for(int i=0;i<gop[u].size();i++)
		{
			int v=gop[u][i];
			if(vis[v]) continue;
			while(!vis[v]) 
				vis[v]=true,q.push(v),
				dis[v]=dis[u]+1,
				v=anc[v][0];              
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	int x;
	for(int i=1;i<n;i++)
	{
		scanf("%d",&x);
		add(i+1,x),add(x,i+1);
	}
	int u,v;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		gop[u].push_back(v);
		gop[v].push_back(u);
	}
	dfs(1,0);
	for(int j=1;j<=20;j++)
		for(int i=1;i<=n;i++)
			anc[i][j]=anc[anc[i][j-1]][j-1];
	bfs();
	for(int i=2;i<=n;i++)
	cout<<(dis[i]==0?-1:dis[i])<<" ";
	return 0;
}

I. Impatient Patient

点击查看代码
/*
1. 标签:贪心 枚举.
2. 突破点:若 i 为最优转移点,则当在 i 挑战失败回到 a_i 时,一定会再从 a_i 走到 i.
*/
#include<bits/stdc++.h>
using namespace std;
const int MAXN=int(5e5+5);
int a[MAXN],x[MAXN];
int main()
{
	int n,T;
	scanf("%d",&T);
	while(T--) {
		scanf("%d",&n);
		for(int i=0;i<=n-1;i++)
			scanf("%d",&a[i]);
		for(int i=0;i<=n-1;i++)
			scanf("%d",&x[i]);
		double ans=n*1.0;
		for(int i=0;i<=n-1;i++) {
			double p=(double)x[i]/100000.0;
			double tp=(p==0.0)?MAXN*1.0:double(i-a[i]+1)/p;
			tp+=a[i];
			ans=min(ans,tp);
		}
		printf("%.12lf\n",ans);
	}
}
posted @ 2023-10-05 09:24  shyiaw  阅读(141)  评论(0)    收藏  举报