usaco#2017#December#Silver

T1-My Cow Ate My Homework

在你的历史课上,你得到了一个很长的作业。这个作业包含了N个题目(3≤N≤100,000),每个题目的成绩在0~10,000之间。
按照惯例,你的老师按照以下方式计算最终成绩:去掉你最低的一个成绩,然后将其余成绩的平均成绩作为最终成绩。但不幸的是,你的宠物牛“贝西”刚刚吃了前K个题目的答案!(1≤K≤N-2)
经过你的一番解释,老师终于相信了你的故事,并且同意对你有答案的题目(没有被吃掉答案的题目)像之前一样给分——通过去掉最低的成绩(如果有多个最低成绩,则只去掉其中一个)并取剩余成绩的平均成绩。
根据这一成绩计算方案,请按升序输出所有可以使你最终成绩最高的K的值。

解法

预处理出前缀和和区间最小值,暴力枚举

ac代码

#include <bits/stdc++.h>
using namespace std;
long long n,a[100010],sum[100010],minn[100010],ans=1,res[100010],cnt=1;
int main()
{
    memset(sum,0,sizeof(sum)),memset(minn,0x3f,sizeof(minn)),res[1]=1,scanf("%lld",&n);
    for(long long i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
    for(long long i=n;i>=1;i--)minn[i]=min(minn[i+1],a[i]);
    for(long long i=2;i<=n-2;i++)
        if((sum[n]-sum[i]-minn[i+1])*(n-ans-1)>(sum[n]-sum[ans]-minn[ans+1])*(n-i-1))ans=i,res[1]=i,cnt=1;
        else if((sum[n]-sum[i]-minn[i+1])*(n-ans-1)==(sum[n]-sum[ans]-minn[ans+1])*(n-i-1))res[++cnt]=i;
    for(int i=1;i<=cnt;i++)printf("%d\n",res[i]);
    return 0;
}

T2-Milk Measurement

最初,农夫约翰的每头奶牛每天生产G加仑的牛奶(1≤G≤10^9)。由于随着时间的推移,奶牛的产奶量可能会发生变化,农夫约翰决定定期对奶牛的产奶量进行测量,并将其记录在日志中。
他的日志中的记录如下:
35 1234 -2
14 2345 +3
第一个条目表明:在第35天,1234号奶牛的产奶量比上次测量时降低了2加仑。
第二个条目表明:在第14天,2345号奶牛的产奶量比上次测量时增加了3加仑。
农夫约翰只有在任何一天内做最多一次测量的时间(即每天最多做一次测量,但可能不做)。不幸的是,约翰有点杂乱无章,他不一定按照时间顺序记下测量结果。为了保持奶牛的产奶动力,农夫约翰自豪地在谷仓的墙上展示了目前产奶量最高的奶牛的照片(如果有若干头奶牛的产奶量最高,他就会展示所有的图片)。
请求出约翰需要调整所展示的照片的次数。
请注意,农夫约翰有一大群奶牛。所以尽管日志中记录了一些奶牛改变了产奶量,但仍然还有很多奶牛的产奶量保持在G加仑。

解法

看题解写的都是线段树,我这么蒟,不会线段树怎么办qwq,我们就来打模拟吧
有几个坑点:
1.当第一名的奶牛产奶量变化,但奶牛编号不变时,不会换照片
2.题目中最后一句话是什么意思呢,就是说一定有奶牛保持在G加仑,也就是说,如果当前计算出来奶牛的最高产奶量不足G加仑,那么贴着照片的不是这头奶牛,而是那些G加仑的奶牛
3.关于具体的模拟做法,就放在程序里吧

ac代码

#include<bits/stdc++.h>
#define u mp[a[i].m]
#define ch a[i].s
using namespace std;
struct node{int t,m,s;}a[101010];
bool cmp(node x,node y){return x.t<y.t;}
int n,g,cow[101010],cnt=100,fi=0,se,fis,ses,ans=0;
//cnt表示奶牛数量
//关于cnt的初值设置为100,是为了解决上面的坑点2
map<int,int>mp;
void find()
{
    se=-0x3f3f3f3f,ses=0;
    for(int i=1;i<=cnt;i++)
        if(cow[i]!=fi&&cow[i]>se)se=cow[i],ses=1;
        else if(cow[i]==se)ses++;
}
//重新寻找第二名
int main()
{
    memset(cow,0,sizeof(cow)),scanf("%d%d",&n,&g);
    for(int i=1;i<=n;i++)scanf("%d%d%d",&a[i].t,&a[i].m,&ch);
    sort(a+1,a+1+n,cmp);
    //先按照记录时间排序
    for(int i=1;i<=n;i++)
    {
        if(!u)u=++cnt;
        //u的定义看上面的define
        //这里就是把编号离散化一下
        if(cow[u]==fi)
        //第一种情况,当前处理的奶牛是排位第一的
        {
            cow[u]+=ch;
            if(ch>0)
            //如果产奶量上升
            {
                if(fis!=1)se=fi,ses=fis-1,fi=cow[u],fis=1,ans++;
                //如果有很多排位第一的奶牛
                //这些奶牛变成第二名,当前奶牛独占第一,照片墙会替换
                else fi=cow[u];
                //如果只有一头排位第一的奶牛,照片墙不会替换
            }
            else
            //如果产奶量下降
            {
                if(fis!=1)
                //如果有很多排位第一的奶牛
                {
                    fis--,ans++;
                    //排位第一的奶牛的数量减少,照片墙替换
                    if(cow[u]>se)se=cow[u],ses=1;
                    //如果当前奶牛的产奶量比第二名大
                    //第二名就变成当前奶牛
                    if(cow[u]==se)ses++;
                    //如果当前奶牛的产奶量等于第二名
                    //第二名奶牛数量增加
                }
                else
                //如果只有一头排位第一的奶牛
                {
                    if(cow[u]>se)fi=cow[u];
                    //如果还比排名第二的产奶量大,照片墙不改变
                    if(cow[u]==se)fi=se,fis=ses+1,ans++,find();
                    //如果等于排名第二的产奶量,第二上升为第一,重新寻找第二名
                    if(cow[u]<se)fi=se,fis=ses,ans++,find();
                    //如果小于排名第二的产奶量,第二上升为第一,重新寻找第二名
                }
            }
        }
        else if(cow[u]==se)
        //如果是第二名
        {
            cow[u]+=ch;
            if(ch<0){ses--;if(!ses)find();}
            //如果产奶量下降的话
            //第二名数量减少
            //如果没有了第二名,就重新寻找
            else
            //如果产奶量增加
            {
                if(cow[u]==fi)
                //如果增加成了第一名
                {
                    ses--,fis++,ans++;
                    //照片墙替换
                    if(!ses)find();
                    //如果没有了第二名,就重新寻找
                }
                else
                //如果没有增加成第一名的话
                {
                    se=cow[u],ses=1;
                    //至少会成为第二名
                    if(se>fi)swap(se,fi),swap(ses,fis),ans++;
                    //还有可能替换第一名,此时照片墙替换
                }
            }
        }
        else
        //如果不是第一第二名
        {
            cow[u]+=ch;
            if(cow[u]==se)ses++;
            if(cow[u]==fi)fis++,ans++;
            //如果变成了第一名,照片墙替换
            else if(cow[u]>se)
            //如果超越第二名但没有变成第一名
            {
                se=cow[u],ses=1;
                //至少成为第二名
                if(se>fi)swap(se,fi),swap(ses,fis),ans++;
                //还有可能替换第一名,此时照片墙替换
            }
        }
    }
    printf("%d\n",ans);
    //可能注释有点啰嗦,请见谅qwq
    return 0;
}

T3-The Bovine Shuffle

FJ坚信快乐的牛可以产出更多的牛奶,因此FJ在牛棚里安装了一个巨大的迪斯科球并且打算让奶牛们学会尬跳舞。
FJ在许多出名的奶牛舞中选择了一种叫做”Bovine Shuffle”的舞蹈。这种舞蹈由FJ的N头奶牛组成。N头奶牛以一种顺序排成一行,接着表演数次”shuffle”。每次的”shuffle”会将奶牛重新排列。FJ为了让奶牛们更加happy,让奶牛们更容易找到重新排列后的位置,他标记了N头奶牛的位置。在最开始,所有奶牛排成一排,第一头奶牛会在位置1(坐标?)上,第二只在2上,以此类推。
我们用N个正整数a_1,a_2…a_n来描述每次的”shuffle”。a_i说明了在位置i上的奶牛在经过这回合的”shuffle”之后,会跑到位置a_i上。令FJ倍感非洲的是,即使i与j不同,a_i也可能会等于a_j!所以可能在一次”shuffle”后,有多头奶牛会跑到同一位置上,在这之后这群奶牛也会一同行动。
作为一名资深的养牛大户&坑牛专家的FJ猛然发现,无论经过多少次的”shuffle”,一直都有k个位置上有奶牛。FJ现在要你在1s1s 内帮他得出k的值,否则就赏你1e18mod10大板!

解法

看了正解都是些图论判环,我们来打玄♂学算法
我们就按照它的步骤模拟,若干次之后看该位置是否还有奶牛
注意要双向模拟

ac代码

#include<bits/stdc++.h>
using namespace std;
int n,a[100005],b[100005],c[100005],ans=0;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)a[i]=b[i]=1,scanf("%d",&c[i]);
    for(int i=1;i<=1000;i++)
    {
        for(int i=1;i<=n;i++)b[c[i]]+=a[i];
        memset(a,0,sizeof(a));
        for(int i=1;i<=n;i++)a[c[i]]+=b[i];
        memset(b,0,sizeof(b));
    }
    for(int i=1;i<=n;i++)if(a[i]||b[i])ans++;
    printf("%d",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: USACO 2021年12月是美国计算机奥林匹克竞赛的一次比赛,是为了选拔美国高中生中最优秀的计算机科学家而举办的。比赛包括四个不同难度级别的编程题目,参赛者需要在规定时间内完成这些题目。这次比赛的题目难度较高,需要参赛者具备较强的编程能力和算法思维能力。 ### 回答2: usaco是一个很受欢迎的美国高中生和大学生参加的计算机竞赛,每年会有四场不同的赛事,分为铜组、银组、金组和白银组等4个不同级别。2021年12月的usaco比赛题目难度中等,4道算法题,主要涉及搜索算法、贪心算法、动态规划和图论算法等方面内容。 题目一是“Convenience Store”,给定一个城市地图,其中包含n个建筑,每个建筑位置有xy坐标,建筑之间可能有道路连通,每个建筑中包含一个便利店和售货员,售货员需要把货物直接送到顾客的门口并统计物资,问售货员需要访问哪些建筑才能完成任务。 题目二是“Longest Path Game”,给定一个有向无环图和起点和终点,每次可以走向图中指向该点的其他点,每走一步需要支付一定的代价,问从起点到终点最少需要支付多少代价并给出最少花费路径。 题目三是“Escape”,给定一个大小为n*m的迷宫,其中包含空地和只能通过特殊方式通过的障碍物,新增一个道具可以消除障碍物,在指定时间内到达终点即可获胜,问是否存在可行解。 题目四是“New Year Travel”,给定一个n个城市构成的圆环和m条单向道路,初次n个城市顺时针排列,经过m次之后重排该圆环,问是否存在一条路径可以在经过圆环的最小路程的前提下遍历所有的城市。 ### 回答3: USACO 2021 12月是一次由美国计算机科学奥林匹克联赛(USACO)组织的编程竞赛。USACO是美国高中生最具影响力的计算机竞赛之一,每年分为四个季度,包含铜组、银组、金组和白金组,涵盖了算法设计、数据结构、图论、搜索、动态规划、计算几何、图像处理等多个领域和真实场景。 本场比赛有铜组、银组和金组三个组别,其中铜组和银组为在线比赛,金组为24小时比赛。比赛难度较高且时间较紧,需要选手在有限时间内完成一系列复杂的程序设计题目。在比赛期间,选手需要具备良好的分析问题、设计算法和编写程序的能力,同时还需要有过硬的数学基础、英语阅读理解能力和编程实践经验。 对于铜组选手来说,需要能够熟练使用基本算法和数据结构来解决题目,如模拟、暴力搜索、递推等;对于银组选手,则需要有更深入的算法思考和程序实现能力,如分治、贪心、二分、动态规划等;而针对金组选手,需要更高的算法挑战和程序优化能力,如图论、网络流、计算几何等。 此次USACO 2021 12月比赛题目难度较大,需要选手们具备扎实的算法基础和良好的程序设计习惯。要想在比赛中取得好成绩,需要选手们克服紧张心理,在比赛前加强对算法知识和代码实践的学习,时刻保持冷静,清晰思路,在有限时间内充分展现自己的编程才能和思维能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值