第一周CF

A. Free Cash

赛中就A了这一题,唉~~继续努力

这题很简单,最主要的是要看懂题目,我看题目的速度太慢,理解慢,oh~~要加强阅读理解能力


题意:Valera要服务客人,每一个客人到达餐店的时间不Valera同,但是顾客来的时候Valera没有活动现金客人就会走,为了保证能留下更多客人,Valera至少要带多少活动现金

其实简单的理解就是求每个客人到达的时间其相同的个数然后取最大值

代码:

#include <iostream>//A
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <stdlib.h>
#include <queue>
using namespace std;
int h;
int m;
int a[100005];
int main()
{
    int n,i,s=0,max=0;
    scanf("%d",&n);
    for(i=0;i<n;i++)
    {
        scanf("%d %d",&h,&m);
        s=h*60+m;
        a[s]++;//每一个时间点它的总数
        if(a[s]>max)//取最大值
        max=a[s];
    }
    cout<<max<<endl;
    return 0;
}

B. Young Table


题意:给出一个表,每一行的个数要大于下一行的个数,也就相当于一个矩阵的左上角三角形区域内,对这些数进行交换操作,使得每一行和每一列都是递增的。

这题其实题目看清楚了也不太难,我当时虽然知道交换步骤数不要求最小,但是要小于数组的个数S,汗颜!!!当时脑子晕了,不管怎样,就算数组完全无序,要交换成有序的,其步骤也不会超过S,想到这个,题目就可以做了

其实我花了很久的时间才弄出这题,刚开始我以为给出的所有数不同,直接用一个数组把它的坐标记录下来就行了,后来发现可以有相同的,那么我就必须改了~~

代码:


#include <iostream>//B
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <stdlib.h>
#include <queue>
using namespace std;
int num[55];
struct node
{
    int x,y;
    int data;
} a[100005],b[100005];//改后a b 数组都是结构体
int s[100005];
bool f(node a,node b)
{
    return a.data<b.data;
}
int main()
{
    int i,j,n,data,k=1,k1=0;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
        scanf("%d",&num[i]);
    for(i=1; i<=n; i++)
    {
        for(j=1; j<=num[i]; j++)
        {
            scanf("%d",&data);
            a[k].x=i;       //放到一维数组里并记录坐标
            a[k].y=j;
            a[k].data=data;

            b[k].x=i;
            b[k].y=j;
            b[k].data=data;
            k++;
            k1++;
        }
    }
    int g=0,g2=0;
    sort(b+1,b+k1+1,f);
    for(i=1; i<=k1; i++)
    {
        if(a[i].data!=b[i].data)//把原数组和排序后的标准数组b做比较

        {
            s[g++]=a[i].x;
            s[g++]=a[i].y;
            int h;
            for(h=1; h<=k1; h++)
            {
                if(a[h].data==b[i].data)//在原数组中找到要交换的那个数
                {
                    break;
                }
            }
            s[g++]=a[h].x;//我错在这里了~我之前是s[g++]=b[i].x ;s[g++]=b[i].y;后来知道快速排序是不稳定的,不能直接用b[i]里的坐标,如果有相同
            s[g++]=a[h].y;//的数,那么b[i].x就不一定==a[h].x,b[i].y就不一定==a[h].y

            swap(a[i].data,a[h].data);
            g2++;
        }
    }
    printf("%d\n",g2);
    int f=0;
    for(i=0; i<g; i++)
    {
        f++;
        if(f==4)
        {
            printf("%d\n",s[i]);
            f=0;
        }
       else
       printf("%d ",s[i]);
    }
    return 0;
}

C. Primes on Interval

题意:给你一个区间【a,b】,让你找到最小的 L(1<=L<=b-a+1),使得对于从任意的一个数 x (a<=x<=b-L+1)开始,连续的L个数即x,x + 1,..., x + L- 1 中至少有K个素数。

如果按平常方法用三个for循环来求极有可能会超时,我弄了好久,用这种方法还是超时。。。。

这题要保证不超时,就必须对素数进行线性筛选,还有重要一步:很重要!很重要!因为每一次都要求一个区间的素数个数,所以索性先求每一个数之前有几个素数,优化一下。。。

由于只用循环来做会超时,因此现在只能采用二分法了,如果上面讲的重要的一步不用,二分也会超时,我试过了。。泪呀!

代码:

#include <iostream>//C
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <stdlib.h>
#include <queue>
using namespace std;
int prim[1000005]= {0};
int pnum[1000005]= {0};
int a,b,k;
int main()
{
    int i,j;
    prim[1]=1;
    for(i=2; i<=1000005; i++)//帅选素数
    {
        for(j=2*i; j<=1000005; j+=i)
            prim[j]=1;
    }
    scanf("%d%d%d",&a,&b,&k);
    for(i=2; i<=b; i++) //先算出每一个数之前有几个素数包括它本身
    {
        pnum[i]=pnum[i-1];
        if(!prim[i])
            pnum[i]++;
    }
    if(pnum[b]-pnum[a-1]<k)
    {
        printf("-1\n");
    }
    else
    {
        int low=1,high=b-a+1,lmid,x;
        while(low<high)
        {
            int flag=0;
            lmid=(low+high)/2;
            for(x=a;x<=b-lmid+1;x++)
            {
                if(pnum[x+lmid-1]-pnum[x-1]<k)
                flag=1;
            }
            if(flag==0)
            high=lmid;
            else
            low=lmid+1;
        }
        printf("%d\n",low);

       /* int l,x;
        for( l=1; l<=b-a+1; l++)//导致超时的代码
        {
            int flag=0;
            for(x=a; x<=b-l+1; x++)
            {
                int sum=pnum[x+l-1]-pnum[x-1];
                if(sum<k)
                {
                    flag=1;
                    break;
                }
            }
            if(x==b-l+2 && flag==0)
            {
                printf("%d\n",l);
                break;
            }
        }*/
    }
    return 0;
}


D.T-decomposition


D题弄了好久,经过和队里的人一起讨论,总算有点思路了,这题来源与树的数分解,题意是把一棵树分成几个集合,把这些集合看成树的结点。若两个集合有公共点,那这两个集合必须相连。其实这个题目就是找集合里点数最小,也就是两个点(一条边),把具有公共点的边连起来,组成一棵新树。(其实看输出样例,就是对于一个点,若至少有两条边附在它上面,就把这些边连起来依次输出!!)
代码:
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
const int M=100005;
int n;
int a[M];
int b[M];
vector<int>V[M];
int main()
{
    int i,j;
    scanf("%d",&n);
    for(i=1; i<n; i++)
    {
        scanf("%d%d",&a[i],&b[i]);
        V[a[i]].push_back(i);
        V[b[i]].push_back(i);
    }
    printf("%d\n",n-1);
    for(i=1; i<n; i++)
        printf("2 %d %d\n",a[i],b[i]);//有n-1条边
    for(i=1; i<=n; i++)
    {
        for(j=1; j<V[i].size(); j++)
            printf("%d %d\n",V[i][j-1],V[i][j]);
    }
    return 0;
}

E题太神,先放先。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值