Codeforces Round #616 题解

Posted ctyakwf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #616 题解相关的知识,希望对你有一定的参考价值。

A题

我们注意到如果存在两个奇数,那么就能满足题目条件,所以我们就从头寻找两个奇数,没有的话就是无解

技术图片
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=600010;
int pos[N]={0};
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        string s;
        cin>>n;
        cin>>s;
        if(n==1){
        cout<<-1<<endl;
        continue;
        }
        
            int cnt=0;
            int i;
            
            for(i=0;i<s.size();i++){
                if(cnt==2)
                break;
                if((s[i]-0)%2){
                    pos[cnt++]=s[i]-0;
                }
            }
            if(cnt<2)
                cout<<-1<<endl;
            else
                cout<<pos[0]<<pos[1]<<endl;        
        
    }
}
 
View Code

B题

可以贪心的想,只要将串设计为0 1 2 3 ……3 2 1 0

这种形式的话是最容易的满足条件的,因为每个数只要大于该数所在位置的下标就行,其他方法都没有这样好

因此我们可以设计两个哨兵,一个l从开始枚举直到第一个不满足条件的,一个r从后面往前枚举

如果l>=r说明满足条件,输出yes因为两边都满足这样的条件,我们只需要取l=r处为中间点,两边按自己的规律枚举即可。

注意判断完全递增和完全递减序列

另外,我的代码有特判一位数的情况,每个一位数都可以,和两位数并且两个都是0的情况,这是不行的,其他两位数都可以

其实不用特判。

我的代码中对每个数都加了1,因为我是从第一位开始枚举的,从第0位开始枚举的不用+1

 

 

技术图片
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=3e5+10;
int a[N];
int main(){
    int t; 
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        int i;
        for(i=1;i<=n;i++){
            cin>>a[i];
            a[i]+=1;
        }
        if(n==1){
            cout<<"Yes"<<endl;
        }
        else if(n==2){
            if(a[1]==1&&a[2]==1)
            cout<<"No"<<endl;
            else
            cout<<"Yes"<<endl;
        }
        else{
        int p1=-2;
        int p2=n+2;
        for(i=1;i<=n;i++){
            if(a[i]<i){
                p1=i-1;
                break;
            }
        }
        for(i=n;i>=1;i--){
            if(a[i]<n-i+1){
                p2=i+1;
                break;
            }
        }
        int flag=0;
        if(p2==n+2||p1==-2)
        flag=1;
        else if(p1>=p2)
        flag=1;
        if(flag==1)
        cout<<"Yes"<<endl;
        else
        cout<<"No"<<endl;
        }
        
        
    }
}
View Code

C题

本题看数据范围发现可以满足O(N^2)的算法,所以我们可以直接上暴力,下面有几个注意点

1.k要更新为min(m-1,k),因为即使k再大我们控制后面的人也没有意义

2.我们要明确一点,控制的人越多越好,这是一种贪心的思路,这也是很显然的,这样你就可以根据情况尽可能的将最大的留给自己

3.我们需要枚举两维,代表的意思是我控制k个人中取前面的人数,和不受控制的人选前面的人数,这样就能枚举出所有情况

tips:第二维可以使用线段树维护,这样可以降低复杂度(虽然本题数据可以暴力水过),有兴趣的同学可以取cf官网上查询官方题解

枚举过程见代码注释

技术图片
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<map>
using namespace std;
typedef long long ll;
const int N=3e5+10;
const int inf=0x3f3f3f3f;
int a[N];
int main(){
    int n;
    int i;
    int m,k;
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m>>k;
        k=min(m-1,k);
        for(i=0;i<n;i++){
            cin>>a[i];
        }
        int ans=-inf;
        int j;
        int tmp;
        for(i=0;i<=k;i++){//k个人中我选i个取前面 
            tmp=inf;
            for(j=0;j<m-k;j++){//剩下的m-1-k人中有j个在前面 
                tmp=min(tmp,max(a[i+j],a[i+j+(n-m)])); //轮到我取的时候我取前面还是最后面的最大值的最小值  
            }
            ans=max(ans,tmp);
        }
        cout<<ans<<endl;
    }
}
View Code

D题 

应该可以用莫队算法解决,下午补上

以上是关于Codeforces Round #616 题解的主要内容,如果未能解决你的问题,请参考以下文章

题解 Codeforces Round #616 (Div. 2) (CF1291)

Codeforces Round #616 (Div. 2) 题解

Codeforces Round #616 (Div. 2)

Codeforces Round #616 (Div. 2)

Codeforces Round #616 (Div. 2)解题报告

Codeforces Round #616 (Div. 2)