[USACO24JAN]2024一月铜组1,3题题解

第一题 Majority Opinion

题目描述

Farmer John 有一项重要的任务 —— 弄清楚要为他的奶牛们购买什么类型的干草。
Farmer John 的 头奶牛( )编号为1到N,每头奶牛喜欢恰好一种类型的干草。他希望他的所
有奶牛都喜欢同一种干草。
为了实现这一目标,Farmer John 可以主持焦点小组访谈。一次焦点小组访谈为让编号从 到 的连续范围内的所有奶牛聚集在一起参加一次访谈。如果有一种干草是小组中超过一半的奶牛喜欢的,则此次焦点小组访谈结束后,所有奶牛最终都会喜欢这种干草。如果不存在这种类型的干草,那么奶牛们不会改变她们喜欢的干草类型。例如,在由 16 头奶牛组成的焦点小组访谈中,需要有其中 9 头或更多的奶牛具有相同的干草喜好,才能使其余奶牛改变其喜好以与之一致。
Farmer John 想知道哪些类型的干草有可能变为同时受到所有奶牛的喜爱。他一次只能主持一个焦点小组访谈,但为了使所有奶牛
都喜欢同一类型的干草,他可以根据需要任意多次地主持焦点小组访谈。

输入格式

输入的第一行包含一个整数 ,为独立的测试用例的数量(1  T  10)。
每一个测试用例的第一行包含 。
第二行包含 个整数,为奶牛们喜爱的干草类型 。

输入保证所有测试用例的 之和不超过 。

输出格式

输出 行,对于每个测试用例输出一行。
如果可能使所有奶牛同时喜欢同一种干草,则以升序输出所有可能的此类干草的类型,否则输出 。在同一行内输出一列整数
时,相邻的数用空格分隔,并确保行末没有多余空格。

输入样例:

5
5
1 2 2 2 3
6
1 2 3 1 2 3
6
1 1 1 2 2 2
3
3 2 3
2
2 1

输出样例:

2
-1
1 2
3
-1
在输入样例中,有 5 个测试用例。
在第一个测试用例中,仅可能使所有奶牛喜欢种类 2 FJ 可以通过主持一次所有奶牛的焦点小组访谈达到这一目的。
在第二个测试用例中,可以证明没有奶牛会改变她们喜爱的干草种类。
在第三个测试用例中,有可能使所有奶牛喜欢种类 1 ,可以通过主持三次焦点小组访谈达到这一目的 —— 首先使奶牛 1 4 进行一次焦点小组访谈,随后使奶牛 1 到 5 进行一次焦点小组访谈,随后使奶牛 1 到 6 进行一次焦点小组访谈。以类似的逻辑,依次操作奶牛 3 到 6,随后是奶牛 2 到 6,随后是奶牛 1 到 6,我们可以使所有奶牛喜欢种类 2。
在第四个测试用例中,有可能使所有奶牛喜欢种类 3 ,可以通过主持一次所有奶牛的焦点小组访谈达到这一目的。
在第五个测试用例中,可以证明没有奶牛会改变她们喜爱的干草种类。

题目大意/程序目标:

每次运算选定一个区间,若在此区间内有一个数字 n 的数量 大于区间总数字数量的一半(如区间有16个数字,则至少需要有9个相同的数字 n ),那么此区间的数都变成 n ,进行多次运算,最后所有的数字都变成相同的数,问这个数能是多少。

思路

可以证明,一个数想成为答案,必须在任意3个连续数字中,至少有两个。

证明方法:3中有2,就能有3,就能有4,...,就能有n,4中有2但3中无2(如1001001),就不能成为答案

就做完了。

代码

#include<bits/stdc++.h>
using namespace std;
int T,n,t[100010],x,y,z,m,ans[100010];
//t数组用于维护区间,ans数组表示这个数是否能成为答案
int main(){
	cin>>T;
	while(T--){
		memset(ans,0,sizeof(ans));
		memset(t,0,sizeof(t));
		cin>>n>>x>>y;
		t[x]++,t[y]++;
		if(n==2){//特判
			if(x==y) cout<<x<<'\n';
			else cout<<-1<<'\n';
			continue;
		}
		if(x==y) ans[x]=1;//这个不能漏
		queue<int>q;
		q.push(x),q.push(y);
		for(int i=3;i<=n;i++){
			cin>>x;
			t[x]++;
			q.push(x);
			if(t[x]>=2) ans[x]=1;
			t[q.front()]--;q.pop();
		}
		bool f=0;
		for(int i=1;i<=n;i++)
			if(ans[i]){
				if(f) cout<<' '<<i;
				else f=1,cout<<i;
			}
		if(!f) cout<<-1;
		cout<<'\n';
	}
	return 0;
}

第二题Cannonball

题目描述

Bessie 已经精通了变成炮弹并沿着长度为N(1≤N≤1e5 )的数轴弹跳的艺术,数轴上的位置从左到右编号为 。她从某个整数位置S(1≤S≤N )开始,以1的起始能量向右弹跳。 如果 Bessie 的能量为k ,则她将弹跳至距当前位置k处向前距离k处进行下一次弹跳。
从1到N的每个整数位置上均有炮击目标或跳板。每个炮击目标和跳板都有一个在0到N范围内的整数值。一个数值为v的跳板会使 Bessie 的能量增加v并反转她的方向。一个数值为v的炮击目标会当着陆时能量不小于v时被击破。着陆在炮击目标上不会改变 Bessie 的能量和方向。被击破的炮击目标将保持击破状态, Bessie 依然可以该炮击目标上弹跳,同样不会改变能量和方向。
如果 Bessie 弹跳无限长的时间或直到她离开数轴,她会击破多少个炮击目标?
如果 Bessie 开始时位于一个她可以击破的炮击目标,她会立刻这样做。类似地,如果 Bessie 开始时位于一个跳板,跳板的效果将 在她第一次跳跃之前生效。

输入格式

输入的第一行包含N和S,其中N为数轴的长度,S为 Bessie 的起始位置。
以下N行描述了每一个位置。其中第i行包含整数qi和vi,如果位置i上有一个跳板则qi=0,位置i上有一个炮击目标则qi=1,vi是位置 上的跳板或炮击目标的数值。

输出格式

输出一个整数,为将被击破的炮击目标数量。

输入样例:

5 2
0 1
1 1
1 2
0 1
1 1

输出样例:

1
Bessie 从坐标 开始,这是一个数值为 的炮击目标,所以她立刻击破了它。然后她弹跳至坐标 ,这是一个数值为 的炮击目
标,所以她无法击破它。她继续弹跳至坐标 ,这改变了她的方向并将她的能量增加了 ,达到 。她跳回至坐标 ,这是一个已经
被击破的炮击目标,所以她继续弹跳。此时,她弹跳至了坐标 ,因此她停了下来。她击破了恰好一个炮击目标,位于坐标 。

第二题直接模拟只有75分(不要问我怎么知道的)猜猜我为什么不写题解

第三题 Balancing Bacteria

题目描述

Farmer John 有N(1 ≤ N ≤ 2e5)块草地排成一行,其中草地 的细菌水平与健康草的细菌水平相差 ai(-1e15 ≤ ai ≤1e15 )。例如,如果a=-3 ,则草地 的细菌水平比正常水平低 3 ,需要额外添加恰好 3 个单位的细菌才能将其提
高到被认为是健康的程度。
Farmer John 想要确保每一块草地都被修复至健康的细菌水平。方便的是,他有两种品牌的农药可以喷洒在他的田地里,一种可以添加细菌,另一种可以去除细菌。当 Farmer John 喷洒任一类型的农药时,他站在草地N(最右边的草地)并为他的喷雾器选择功率等级L(1≤L≤N )。
喷雾器对靠近 Farmer John 的草地效果最大,随着距离增加效果逐渐减弱。如果 Farmer John 选择添加细菌的农药,则L单位的细菌将被添加至草地N,L-1单位添加至草地N-1,L-2单位添加至草地 N-2,以此类推。草地1...N-L不会得到任何
Farmer John 使用喷雾器的最少次数,使得每块草地都具有健康草的推荐细菌值。输入保证答案不超过1e9。
注意这个问题涉及到的整数可能需要使用 64 位整数型(例如, C/C++ 中的 "long long" )。

输入格式

输入的第一行包含N。
第二行包含N个整数a1,...,aN,为每块草地的初始细菌水平。

输出格式

输出一个整数,为使每块草地都具有健康草的推荐的细菌值所需使用喷雾器的最少次数。

输入样例1:

2
-1 3

输出样例1:

6
使用去除细菌的农药,功率等级为 1 ,使用五次。然后使用添加细菌的农药,功率等级为 ,使用一次。

输入样例2:

5
1 3 -2 -7 5

输出样例2:

26

题目大意/程序目标:

见思路

思路

做好心理准备,即使你看得懂思路也可能看不懂代码!!!

差分

这是一道好题。

可以发现:一次计算过程就相当于 \pm (1,2,3,...,L-1,L),而将此序列差分一下就是(1,1,1,...,1,1),看起来很好看,所以选定思路

有了差分这个思路后,我们将原数组差分,得到数组b,差分有一个特性就是差分数组求前缀和是原数组。可以证明 将b数组后L位\pm(1,1,1,...,1,1)后的前缀必定=原数组 \pm(1,2,3,...,L-1,L),所以就可以把 题目:原数组 \pm(1,2,3,...,L-1,L)重复多次变成0,转化为差分数组 \pm(1,1,1,...,1,1)重复多次变成0

因为每个数都是独立的,这一位加了多少和上一位是没关系的,所以我们可以直接从第一位开始。

因为每次差分数组加减都是从某一位到最后一位都加1的,所以这一位加了多少,下一位也是加多少,又因为我们是从第一位开始的,那么当b[i-1]=0时,后面的数一定都减了b[i-1],那么b[i]想等于0就得减去b[i]-b[i-1],就是进行b[i]-b[i-1]次操作。

如果不好理解的话,我们先设一个k表示前面已经用了k此操作,每次操作都是在前面进行的,所以后面的数一定都减了k,b[i-1]想等于0就得减去b[i-1],原来就减了k,就只用减b[i-1]-k。到i+1时,k就变成k+(b[i-1]-k),(原来的次数+新增的次数)刚好是b[i-1],所以每一次k=b[i],就不用k了,b[i]=b[i]-k=b[i]-b[i-1],就是进行b[i]-b[i-1]次操作

注意:要用LL,因为不知b[i]和b[i-1]谁大谁小,所以要用abs

#include<bits/stdc++.h>
using namespace std;
long long n,a[200010],b[200010],ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i]-a[i-1],ans+=abs(b[i]-b[i-1]);
	cout<<ans;
	return 0;
}

 此代码还能简化:

#include<bits/stdc++.h>
using namespace std;
long long n,ax,ay,bx,by,ans;
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>ay,by=ay-ax,ans+=abs(by-bx),ax=ay,bx=by;
	cout<<ans;
	return 0;
}

 最终时间复杂度O(n),空间复杂度O(1)

  • 32
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
USACO2022金组是国际在线判系统USACO的最高级别,目难度较高,在该比赛中取得好成绩是一项巨大的成就。以下是对该比赛的一些目解析。 第一:“交通计划” 目要求:给定一个n个节点的有向图,每条边有一个长度,希望添加最少的边使得所有节点连通,求最小生成树的权值和。 解析:该可以使用Kruskal算法求解,将每条边按权值从小到大排序,再依次加入,判断加入的边是否会形成环,若形成则不加入,直到所有节点连通为止。此时Kruskal算法得到的最小生成树的权值和即为所求。 第二:“点火计划” 目要求:给定一个n个节点的有向图,每条边有一个权值和一个点火时长,每个节点有一个点火启动时刻和时刻结束时刻,希望从其中选出一些边点火,使得所有节点都可从点火的边出发到达,且所选点火边的总点火时长最小。 解析:该可以使用最小费用最大流算法求解。将每条边看做一个容量为1,费用为点火时长的边,源点向节点的点火边容量为1,费用为0的边,节点的点火边向汇点的容量为1,费用为0的边,对这个网络进行最小费用最大流即可得到所选边的总点火时长最小。 第三:“美味佳肴” 目要求:给定n个菜品,每个菜品有它的权值和两个类别,希望选出k个菜品,使得选出的菜品数量在每个类别中都不超过$\frac{k}{3}$个,且所选菜品的权值和最大。 解析:该可以使用动态规划求解。设$f[i][j][k]$表示前i个菜品中,选择j个一类菜品,选择k个二类菜品的最大权值和,状态转移方程为$f[i][j][k]=max(f[i-1][j][k],f[i-1][j-1][k]+a[i],f[i-1][j][k-1]+b[i])$,其中a[i]为i号菜品的权值,若为一类则为该权值,否则为0,b[i]为i号菜品的权值,若为二类则为该权值,否则为0。最终答案为$f[n][$k/3$][$k/3$]。 以上是对USACO2022金组的部分目的解析,USACO比赛是全球范围内的计算机竞赛,竞争非常激烈,能够在该比赛中脱颖而出是一项非常棒的成就。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值