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

本文深入探讨了编程领域的多个方面,包括算法、数据结构、测试、版本控制、项目管理等核心概念。通过实例分析和代码示例,帮助读者掌握从基本原理到实际应用的全过程。同时,文章还涵盖了不同技术领域的最新趋势和发展,如AI音视频处理、大数据开发、嵌入式硬件等,旨在提供全面的技术视角和实践指导。

传送门:点击打开链接

A题:给定一个长度为n的序列。给定操作:删除除首尾元素以外的任何一个元素。得到一个新的序列。新序列相邻两个元素间的差。求每一次差的最大值的最小值样例已经给的很清楚了。

思路:数据量很小,直接暴力模拟,时间复杂度n*n。当然这道题方法很多。

AC代码

#include <bits/stdc++.h>
#define debug puts("xxxxxxx")
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=100005;
int a[maxn];
int cha;
int main()
{
    int i,j,n,mn=-inf,ans=inf;
    cin>>n;
    for(i=0;i<n;i++) cin>>a[i];
    a[n]=-inf;
    for(i=1;i<n-1;i++)
    {
       int pre=0,next=1,cnt=0;
       mn=-inf;
       while(next<n)
       {
           if(pre==i) pre++;
           if(next==i) next++;
           if(pre==next) next++;
           //if(next==n) break;
           cha=a[next]-a[pre];
           mn=max(mn,cha);
           pre++;
           next++;
       }
       ans=min(ans,mn);
    }
    cout<<ans<<endl;
   return 0;
}


B题

题意:给定一个位数为n的数字。有以下两种操作。1:将每一位加1(9变成0)。2:将每一位右移(最右一位到最左)。可以得到很多新的数字。比较这些数字的大小(比较大小时忽略前导0),输出最小值。

思路:最小值必然是首位数字为0。由于数据量很小,因此,我们可以这样操作:枚举每一位,将该位变成0,然后将该位放到第一位。将所有结果保存在string类型数组中,按照字典序排序,输出字典序最小的即可。

AC代码

#include <bits/stdc++.h>
#define debug puts("xxxxxxx")
#define pi (acos(-1.0))
#define eps (1e-8)
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=1005;
int a[maxn],b[maxn];
string s[maxn];
char x[maxn];
int main()
{
    int n,i,j,tmp;
    cin>>n;
    cin>>x;
    for(i=0; i<n; i++) a[i]=x[i]-'0';
    for(i=0; i<n; i++)
    {

        tmp=(9-a[i]+1) %10;
        for(j=0; j<n; j++)
        {
            b[j]=a[j];
        }
        for(j=0; j<n; j++)
        {
            b[j]=(b[j]+tmp)%10;
        }
        int cnt=0;
        while(cnt<n-1)
        {
            s[i]+=(b[(i+1+cnt)%n]+'0');
            cnt++;
        }
    }
    sort(s,s+n);
    cout<<0;
    cout<<s[0]<<endl;
    return 0;
}

C题

题意:给定一个n*m的字符矩阵。给定操作:删除某些列,使得每一行比上一行的字典序大。求出最少操作次数。

思路:对于每一列,比较a[j+1]和a[j]的大小。如果a[j+1] > a[j],那么之后的列第j和第j+1行就不需要比较了。若a[j+1] < a[j],那么这一列就要删除。用一个vis数组标记每一行是否还需要判断。对于需要判断的判断即可。

AC代码

#include <bits/stdc++.h>
#define debug puts("xxxxxxx")
using namespace std;
typedef long long ll;
const int maxn=105;
char a[maxn][maxn],vis[maxn];
int n,m;
int main()
{
    cin>>n>>m;
    int i,j,ans=0;
    for(i=0; i<n; i++) cin>>a[i];
    int cnt=n-1;
    memset(vis,0,sizeof(vis));
    for(i=0; i<m; i++)
    {
        if(cnt==0) break;
        int flag=0;
        for(j=0;j<n-1;j++)
        {
            if(a[j][i]>a[j+1][i] && !vis[j])
            {
                ans++;
                flag=1;
                break;
            }
        }
        if(!flag)
        {
            for(j=0;j<n-1;j++)
                if(a[j][i]<a[j+1][i] && !vis[j]) vis[j]=1,cnt--;

        }
    }
    cout<<ans<<endl;
    return 0;
}

D题

题意:P和G两个人进行网球比赛。每一局有一个分数t,当一个人赢完s局时,比赛结束。每·没结束一局,双方比分清零。现在给定n个数,每个数可能是1或2。是1表示P赢1分,2表示G赢一分。那么问题来了,s和t的组合可能是哪些情况?

思路:枚举分数t,对于当前的t,模拟s。由于数据量较大,模拟时要用二分。

AC代码

#include <bits/stdc++.h>
#define debug puts("xxxxxxx")
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
const int maxn=100005;
int n,f[maxn][3];
pair<int,int> ans[maxn];
int get_pos(int pos,int k,int c)
{
    int l=pos+1,r=n,m;
    if(f[n][c] - f[pos][c] < k) return inf;
    while(l<r)
    {
        m=(l+r) >> 1;
        if(f[m][c]-f[pos][c]<k) l=m+1;
        else r=m;
    }
    return l;
}
int get_ans(int k)
{
    int pos=0,pos1=0,pos2=0,win1=0,win2=0,last;
    while(true)
    {
       pos1=get_pos(pos,k,1);
       pos2=get_pos(pos,k,2);
       if(pos1>n && pos2>n) return -1;
       if(pos1<pos2)
       {
           pos=pos1;
           last=1;
           win1++;
       }
       else if(pos1>pos2)
       {
           pos=pos2;
           last=2;
           win2++;
       }
       if(pos==n)
       {
           if(last==1 && win1<=win2) return -1;
           if(last==2 && win2<=win1) return -1;
           return max(win1,win2);
       }
    }
}
int main()
{
    cin>>n;
    int i,tmp;
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)
    {
        cin>>tmp;
        f[i][tmp] = 1;
    }
    for(i=1;i<=n;i++)///到第i个1或者2的个数
    {
        f[i][1] += f[i-1][1] ;
        f[i][2] += f[i-1][2] ;
    }
    int cnt=0;
    for(i=1;i<=n;i++)
    {
        int res=get_ans(i);
        if(res!=-1) ans[cnt++]=make_pair(res,i);
    }
    sort(ans,ans+cnt);
    cout<<cnt<<endl;
    for(i=0;i<cnt;i++)
        cout<<ans[i].first<<" "<<ans[i].second<<endl;

    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值