[COCI2014-2015#4] PŠENICA

发布时间 2023-09-08 09:39:02作者: 是002呀

题目分析

$50pts:$

瞎搞就行

$80pts$

大家看到这道题,肯定第一想法是直接暴力去模拟,就是左边一个右边一个然后算到只剩两个,自以为这个复杂度是线性的,然后就会拿到 $80$ 分的好成绩,因为你每模拟一个数,到了下一个数,这个数还要再被模拟一次,这样复杂度就会退化到平方级这样的话 $10^5$ 的数据就妥妥的超时了

$100pts$

正解就是在 $80$ 分的代码上进行优化,如果我们每次按照,这个数拥有的个数去模拟的话,就可以把模拟次数控制在线性,但是这样的话,一边模拟一边计算胜利者很麻烦,所以我们到最后进行一下特判首先,如果
$n\leq2$,因为之前的循环过后还是 Mirko 先手,所以 Mirko 直接输掉了;如果 $n=3$,那么有三种情况:

  1. 最矮小麦的根数等于最高小麦的根数,Mirko 是先手,所以 Mirko 获胜;
  2. 最矮小麦的根数大于最高小麦的根数,Slavko 会先取完,所以 Slavko 获胜
  3. 最矮小麦的根数小于最高小麦的根数,与第二种情况相反,Slavko 会输掉。

std

#include<bits/stdc++.h>
#define int long long 

const int N=100005;

using namespace std;

int n,m;
int a[N],cnt[N];//a是记录小麦高度的种类,cnt是记录每种高度的小麦根数

signed main(){
    cin>>m;
    for(int i=1;i<=m;i++){
        int num;
        cin>>num;
        if(!cnt[num]) a[++n]=num;//防止a中出现重复
        cnt[num]++;
    }
    sort(a+1,a+1+n);//对所有的高度要先进行排序,保证其单调性
    int l=1,r=n;
    while(n>3){/*小于等于3的时候就可以退出进行特判*/
        if(cnt[a[l]]>cnt[a[r]]){
            cnt[a[l]]-=cnt[a[r]];//多的要减去少的,少的不变,因为下面还要用到
            cnt[a[l+1]]+=cnt[a[r]];
            cnt[a[r-1]]+=cnt[a[r]];
            r--,n--;
        }
        else if(cnt[a[l]]<cnt[a[r]]){
            cnt[a[r]]-=cnt[a[l]];
            cnt[a[l+1]]+=cnt[a[l]];
            cnt[a[r-1]]+=cnt[a[l]];
            l++,n--;
        }
        else{
            cnt[a[l+1]]+=cnt[a[l]];
            cnt[a[r-1]]+=cnt[a[r]];
            l++,r--;
            n-=2;
        }
    }
    if(n<=2) cout<<"Slavko"<<endl<<a[l]<<" "<<a[r];
    else{
        if(cnt[a[l]]>cnt[a[r]]) cout<<"Slavko"<<endl<<a[l]<<" "<<a[l+1];
        else cout<<"Mirko"<<endl<<a[r-1]<<" "<<a[r];
    }//按照题目给出的三种情况进行分类讨论
    return 0;
}