czl蒻蒟的OI之路4

  • XJOI奋斗群蒻蒟群群赛5 RANK排名15
      • T1Curriculum Vitae WA五次后AC
          • 题意
          • 分析过程
          • 给出题解
      • T2Math Show WA十次后AC
          • 题意
          • 分析过程
          • 给出题解
      • T3Four Segments 未AC
          • 题意
          • 分析过程
          • 给出题解
      • T4Monitor 未AC
          • 题意
          • 分析过程
          • 给出题解
      • T5Chemistry in Berland 未AC
          • 题意
          • 分析过程
          • 给出题解
      • T6Random Query 2次WA后AC
          • 题意
          • 分析过程
          • 给出题解
      • 蒻蒟总结

—>XJOI奋斗群(蒻蒟群)群赛5<— RANK排名15

T1:Curriculum Vitae (WA五次后AC)

题意:

给你一串01数列,要求你可以删掉几个数据,使得新的出的数组里面,1的后面没有0。让你输出最后能留下的最大的数据个数。

分析过程:

刚开始没有考虑的太深,以为只要找出第一个1的位置,然后把后面所有的0都删掉就行了,结果这题坑的地方在于还可以删掉0。而1后面只不可能会有0的,所以只要遍历每一个数,计算这个数前面1的数量与后面零的数量,就可以判断这个数该不该删。

给出题解:
#include
using namespace std;

int a[105];  
int main()  
{  
    int i,j,n,ans,t;  
    cin>>n;  
    ans=1;  
    for(i=1;i<=n;i++)  
    cin>>a[i]; 
    for(i=1;i<=n;i++)  
    {  
        t=0;  
        for(j=1;j<=i;j++)  
        {  
            if(!a[j])  
                t++;  
        }  
        for(j=i;j<=n;j++)  
        {  
            if(a[j])  
                t++;  
        }  
//        cout<
        ans=max(ans,t);  
    }  
    cout<return 0;  
}  
#include
using namespace std;

long long int n,k,t,ans;
int main()
{
    cin>>n>>k>>t;
    if(t<=k)ans=t;
    else if(t>k&&t<=n)ans=k;
    else if(t>n)ans=n+k-t;
    cout<

T2:Math Show (WA十次后AC)

题意:

有n个任务,而每个任务都有k个子任务,且分别会花费一定时间。当做完一个子任务时,分数会++,当做完一整个任务时,分数会额外++。让你求在一定时间内,能够获得的最大的分数。

分析过程:

刚开始考虑的不够全面,仅仅只是想着比较一下只完成子任务与尽量完成多的整任务两种情况分数的大小。然而中间仍有很多种完成一部分的整任务,然后剩余时间用来完成分任务的情况,这些情况的分数可能会更高,而且本题数据不大,所以可以一个一个遍历过去。

给出题解:
#include
using namespace std;

int main()
{
    long long n,k;
    long long b,t,sheng;
    long long ans=0,point=0,p1=0;
    int z[100],cnt[100];
    cin>>n>>k>>t;
    for(int i=1;i<=k;i++)
    {
        cin>>z[i];
        cnt[i]=n;
        ans=ans+z[i];
    }
    sort(z+1,z+k+1);
    for(int i=0;i<=n&&t>=ans*i;++i)
    {
//      cout<<"i="<
        p1=(k+1)*i;
 //     cout<
        sheng=t-i*ans;
        for(int j=1;jfor(int m=1;m<=n-i;++m)
            {
                if(sheng>=z[j])
                {
                    sheng=sheng-z[j];
                    p1++;
                }
            }

        }
        point=max(point,p1);
    }
    cout<return 0;
}

T3:Four Segments (未AC)

题意:

给你一个数组,然后让你确定3个点,dilim1,dilim2,dilim3让第0~dilim1的所有数的和减去dilim1~dilim2的所有数的和,加上dilim2~dilim3的所有数的和,减去dilim3~n所有数的和。让你求这个值的最大值。

分析过程:

这题如果用O(n^3)的解法,会 TLE,所以可以先暴力列出dilim2的值,再在剩余两个区间里找出两个最大的数作为dilim1,dilim3的值,然后求出算术值,进行比较,这样的复杂度为O(n^2),不会TLE。

给出题解:
#include
#define maxn 100000
#define inf 0x7f7f7f
typedef long long LL;
using namespace std;

int main()
{
    LL n;
    LL a[maxn];
    LL d0,d1,d2,ad0,ad1,ad2,x,y,z,max=-inf;
    LL qian[maxn];
    cin>>n;
    memset(qian,0,sizeof(qian));
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        qian[i]=qian[i-1]+a[i]; 
//      cout<
    }
//    cout<
//   cout<
    for(int ad1=0;ad1<=n;ad1++)
    {
        d1=ad1;
        d2=d0=d1;
        for(int ad0=0;ad0<=ad1;ad0++)if(qian[ad0]>=qian[d0]){d0=ad0;}
        for(int ad2=ad1;ad2<=n;ad2++)if(qian[ad2]>=qian[d2]){d2=ad2;}
        if((qian[d0]+qian[d2]-qian[d1])>=max)
        {
            max=qian[d0]+qian[d2]-qian[d1];
            x=d0;
            y=d1;
            z=d2;   
        } 
    }
    cout<" "<" "<//  cout<
    return 0;
}

T4:Monitor (未AC)

题意:

给你一个n*m的矩阵,其中有一些点会在一定时间坏掉,给你一个值k,让你求在某个时间,存在k*k的矩形的所有点都坏掉了。让你求最小的时间。

分析过程:

如果暴力枚举k*k的矩形,果断在第26个点TLE。可以先求每一行在满足长度为k的最小破碎时间,每一列也如此,就可以用更短的时间求出坏掉的最小时间。

给出题解:
#include
using namespace std;
int n,m,k,q,a[505][505],d[505][505];
int main()
{
    cin>>n>>m>>k>>q;
    for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)a[i][j]=1e9+7;
    for(int i=1;i<=q;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        a[x][y]=w;
    }
    int ans=1e9+7;
    for(int i=1;i<=n;i++)
    {
        for(int j=k;j<=m;j++)
        {
            d[i][j]=a[i][j];
            for(int kk=j-k+1;kkfor(int i=n;i>=k;i--)
    {
        for(int j=k;j<=m;j++)
        {
            for(int kk=i-k+1;kkif(ans==1e9+7)cout<<-1;
    else cout<return 0;
}

T5:Chemistry in Berland (未AC)

题意:

给你n种材料,每种材料可以互相转换,转换的值在下面n-1行会给出,然后让你判断能不能让每种材料都达到指定的值。

分析过程:

既然这可以化成一棵树,那就可以先从这棵树的叶子节点开始遍历。因为该叶子只能由其父亲节点转化而来,所以如果该节点的值小于指定值,则由其父亲节点补全,反之则由其多余的返回去补父亲节点,最后判断这棵树的根节点是否到达给定值即可。然er我并没有用树(表示不怎么会),不过思路还是差不多的。

给出题解:
#include 
using namespace std;
typedef long long ll;

int n;
double ans[100001];
ll x[100001],k[100001];

int main() 
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>ans[i];
    }
    for(int i=1;i<=n;i++)
    {
        ll a;cin>>a;
        ans[i]=a-ans[i];
    }
    for(int i=2;i<=n;i++)
    {
        cin>>x[i]>>k[i];
    }

    for(int i=n;i>1;i--)
    {
        if(ans[i]>0)
        {
            ans[x[i]]+=k[i]*ans[i];
        }else
        {
            ans[x[i]]+=ans[i];
        }
        ans[i]=0;
    }
    if(ans[1]<=0)cout<<"YES";
    else cout<<"NO";
    return 0;
}

T6:Random Query (2次WA后AC)

题意:

给你一串数列,你可以两两交换数字(实际没有卵用,只要理解为选择2个数就可以了),并计算期望值,期望值就是你的所有选择中不相同数字的个数之和,除以总方案数。

分析过程:

选择两个数,如果两数相同,贡献的期望值为1,而如果两数不同,贡献的期望值则为2。而这题可以枚举每个数字,计算数字的期望值之和,再除以方案数就行了,但注意保留一下数位,大概8位就够了。

给出题解:
#include
using namespace std;
int main()
{
   int n,a,head[100000]={0};
   double ans;
   cin>>n;
   ans=-n;
   for(int i=1;i<=n;i++)
   {
    cin>>a;
    ans+=(long long )(i-head[a])*(n-i+1)*2;
    head[a]=i;
   }    
   ans=(double)ans/(double)(n*n);
   printf("%lf",ans);
}

蒻蒟总结:

很水的一天(听说玩了小恐龙会爆零,或许是真的),题目比较难理解,做题时也因为题目做不出而感到心急,但仔细想想,这时候爆零也总比比赛爆零好。而且今天还是有大佬AC了4题,很不甘心啊,但只要订正了题目了,RANK什么的都不重要了。

附上吴老师的一句话:“学计算机的人,绝不轻易认输!!!”

你可能感兴趣的:(蒟蒻OI之路)