比赛5 总结

来源:互联网 发布:手机4g网络提速方法 编辑:程序博客网 时间:2024/06/05 03:19

  • T1
    • 题面
    • 题意
    • 方法
    • 代码
    • 错误点
  • T2
    • 题面
    • 题意
    • 方法
    • 代码
  • T3
    • 题面
    • 题意
    • 方法
    • 代码
    • 错误点
  • T4
    • 题面
    • 题意
    • 方法
    • 代码
  • T5
    • 题面
    • 题意
    • 方法
    • 代码
  • T6
    • 题面
    • 题意
    • 方法
    • 代码

T1

题面

题意

输入n和长度为n的由0,1组成的序列,删去一些数,使1后面没有0.

方法

因为有1后,就不能有0,故仅需决定从哪个1开始删去后面的0,且之前不能有1.

代码

#include<bits/stdc++.h>using namespace std;int n,a[101],b[101],bb=0;int main(){    int i,p,q,ans=0;    cin>>n;    for(i=1;i<=n;i++)    {        cin>>a[i];    }    for(i=1;i<=n;i++)    {        if(a[i]==1)        {            ans++;//记录下全部为1时的答案            bb++;            b[bb]=i;//统计1的个数,并且记录下1的位置        }    }    for(i=1;i<=bb;i++)    {        ans=max(ans,bb+b[i]+1-2*i);//将ans与若改点开始替换比较    }    ans=max(ans,n-bb);//最后与全部为0时比较    cout<<ans;}

错误点

未与全部为0时比较,且bb+b[i]+1-2*i计算错误.

T2

题面

题意

输入n,k,t与长度为k的序列.序列表示每个子任务依次要多久
有n个任务,每个任务必须按序列依次完成子任务,完成一个子任务,加一点,一个总任务,再加一点,问在t时间内最多可以获得几点.

方法

先排序,统计最多能做m个总任务,枚举0到m,多余时间从小任务开始做,找到最大值即可。

代码

#include<bits/stdc++.h>#define N 501#define M 1000000000using namespace std;int a[N],m,n,k,q,t,sum;int zs(int sy,int rw){    int i,p,z=0;    for(i=1;;i++)    {        if(a[i]*rw<=sy)        sy-=a[i]*rw;        else        {            p=i;            break;        }        z+=rw;    }    for(i=1;;i++)    {        if(sy>=a[p])        {            sy-=a[p];            z++;        }        else break;    }    return z;}int main(){    int i,j,ans=0,an=0,tt;    cin>>n>>k>>t;    tt=t;    for(i=1;i<=k;i++)    {        cin>>a[i];        sum+=a[i];    }    m=t/sum;    if(t>=sum*n)//特判能否全做完    {        cout<<n*(k+1);        return 0;    }    sort(a+1,a+k+1);    for(i=0;i<=m;i++)    {        t=tt;        t-=sum*i;        ans=0;        ans+=i*(k+1);        ans+=zs(t,n-i);        an=max(an,ans);    }    cout<<an;}

T3

题面

题意

输入n与长度为n的整数序列,确定其中三个点,分成四段,使一三段减二四段的差最大

方法

枚举中间点并计算它前后两段所能取到的最大与最小值(用前缀和维护),并比较哪个最终结果最大.

代码

#include<bits/stdc++.h>#define N 5001#define ll long longusing namespace std;ll cnt[N],n;int main(){    ll i,j,mn=1,mx=-1,ans1,ans2,ans3,an1,an2,an3,mx2=-100000000000;    cin>>n;    for(i=1;i<=n;i++)    {        cin>>cnt[i];        cnt[i]+=cnt[i-1];    }    //cnt[i]表示第一个数到它的和    for(i=0;i<=n;i++)//枚举第二个数    {        an2=i;        mn=1;        mx=-1;        for(j=i;j>=0;j--)        {            if(cnt[i]-cnt[j]<mn)            {                mn=cnt[i]-cnt[j];                an1=j;            }        }//向前取一段找到最小值        for(j=i;j<=n;j++)        {            if(cnt[j]-cnt[i]>mx)            {                mx=cnt[j]-cnt[i];                an3=j;            }        }//向后取一段找到最大值        if(cnt[an1]+cnt[an3]-cnt[an2]>mx2)        {            mx2=cnt[an1]+cnt[an3]-cnt[an2];            ans1=an1;            ans2=an2;            ans3=an3;        }//比较一三和的最大值来找答案    }    cout<<ans1<<" "<<ans2<<" "<<ans3;}

错误点

先找一段和最小的序列,头为ans1,尾为ans2,再以n为尾往前找一段和最小的序列,头为ans3.
反例如下
5
1,-9,1,-9,-9.
答案应为1 2 3
该方法输出1 5 5
因为第一次找的序列为-9到-9,是第四段为0.

T4

题面

题意

输入矩阵长宽m,n和k,q.
接下来q行,每行写x,y,t,表示坐标为x,y的t时为1.
若矩阵中有边长为q的正方形内均为1,则输出该时间
若没有这个时间,则输出-1.

方法

将矩阵初值负为10^9+1,将时间输入矩阵,每个数变成它右边k-1数与自己的最大值,然后每个数变成它下面k-1个数和自己的最大值,再扫一遍,找到方阵的最小值,若为10^9+1,则输出-1,否则输出最小值。

代码

#include<bits/stdc++.h>#define ll long long#define N 510#define M 1000000001using namespace std;ll a[N][N],m,n,k,q;int main(){    ll i,j,ii,jj,x,y,t,mn=M;    cin>>m>>n>>k>>q;    memset(a,M,sizeof(a));    for(i=1;i<=q;i++)    {        cin>>x>>y>>t;        a[x][y]=t;    }    for(i=1;i<=m-k+1;i++)    {        for(j=1;j<=n;j++)        {            for(ii=0;ii<k;ii++)            {                a[i][j]=max(a[i][j],a[i+ii][j]);            }        }    }    for(i=1;i<=m;i++)    {        for(j=1;j<=n-k+1;j++)        {            for(ii=0;ii<k;ii++)            {                a[i][j]=max(a[i][j],a[i][j+ii]);            }        }    }    for(i=1;i<=m-k+1;i++)    {        for(j=1;j<=n-k+1;j++)        {            mn=min(a[i][j],mn);        }    }    if(mn==M) cout<<-1;    else cout<<mn;}

T5

题面

题意

方法

代码

T6

题面

题意

输入长度为n的序列,随机选择r和l,若r< l,则交换,答案为其间的不同数字的个数
输出所有答案的平均值

方法

若要一个数贡献,则要在它与该数上一次出现的地方加一到该数与该数到n两个区间,各选一个,故可以算出该数贡献的种类数,最后加起所有数贡献的种类数除以总方案数n*n即可。

代码

#include<bits/stdc++.h>#define N 1000001#define ll long longusing namespace std;ll last[N];double n;int main(){    ll i,j,p;    double ans;    cin>>n;    ans=-n;//出去选择相同数时的重复情况     for(i=1;i<=n;i++)    {        cin>>p;        ans+=(i-last[p])*(n-i+1)*2;        last[p]=i;//last记录该数上一次出现的位置    }    printf("%.6lf",ans/(n*n));}
原创粉丝点击