9.6模拟赛

80+50+0=130

T1 第二题

【问题描述】

给你两个日期,问这两个日期相差了多少毫秒。

【输入格式】

两行,每行一个日期,日期格式保证为“YYYY-MM-DD hh:mm:ss”这种形式。第二个日期时间

一定比第一个日期的时间要大。两个日期的年份一定都是21世纪的年份。

【输出格式】

一行一个整数代表毫秒数。

【样例输入 1】

2000-01-01 00:00:00

2000-01-01 00:00:01

【样例输出 1】

1000

【样例输入 2】

2000-01-01 00:00:00

2000-11-11 00:00:00

【样例输出 2】

27216000000

【样例解释】

从前有座山。

【数据范围与规定】

对于10%的数据,两个日期相同。

对于20%的数据,两个日期只有秒数可能不同。

对于30%的数据,两个日期只有秒数、分钟数可能不同。

对于40%的数据,两个日期的年月日一定相同。

对于60%的数据,两个日期的年月一定相同。

对于80%的数据,两个日期的年份一定相同。

对于100%的数据,两个日期一定都是21世纪的某一天,且第二个日期一定大于第一个日期。

题解:if判断80分。

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

int n,y,r,s,f,m,nn,yy,rr,ss,ff,mm;

int cd[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int read(){
    int x=0;char ch=getchar();
    for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';
    return x;
}

int hmd(int l,int r){
    int sum=0;
    for(int i=l;i<=r-1;i++)sum+=cd[i];
    return sum;
}

int main(){
    freopen("two.in","r",stdin);
    freopen("two.out","w",stdout);
    n=read();y=read();r=read();s=read();f=read();m=read();
    nn=read();yy=read();rr=read();ss=read();ff=read();mm=read();
//    printf("%d %d %d %d %d %d
",n,y,r,s,f,m);
//    printf("%d %d %d %d %d %d
",nn,yy,rr,ss,ff,mm);
    if(n==nn&&y==yy&&r==rr&&s==ss&&f==ff&&m==mm){
        printf("0
");return 0;
    }
    if(n==nn&&y==yy&&r==rr&&s==ss&&f==ff&&m!=mm){
        printf("%d
",(mm-m)*1000);return 0;
    }
    if(n==nn&&y==yy&&r==rr&&s==ss&&f!=ff){
        mm-=m;
        if(mm<0){mm+=60;ff--;}
        printf("%d
",(ff-f)*60*1000+mm*1000);
        return 0;
    }
    if(n==nn&&y==yy&&r==rr&&s!=ss){
        mm-=m;
        if(mm<0){mm+=60;ff--;}
        ff-=f;
        if(ff<0){ff+=60;ss--;}
        cout<<(long long)((ss-s)*60*60*1000+ff*60000+mm*1000);
        return 0;
    }
    if(n==nn&&y==yy&&r!=rr){
        mm-=m;
        if(mm<0){mm+=60;ff--;}
        ff-=f;
        if(ff<0){ff+=60;ss--;}
        ss-=s;
        if(ss<0){ss+=24;rr--;}
        cout<<1LL*mm*1000+ff*60000+ss*60*60000+(rr-r)*24*60*60000;
        return 0;
    }
    if(n==nn&&y!=yy){
        mm-=m;
        if(mm<0){mm+=60;ff--;}
        ff-=f;
        if(ff<0){ff+=60;ss--;}
        ss-=s;
        if(ss<0){ss+=24;rr--;}
        rr-=r;
        if(rr<0){rr+=cd[yy-1];yy--;}
        cout<<1LL*hmd(y,yy)*24*60*60000+rr*24*60*60000+ss*60*60000+ff*60000+mm*1000;
        return 0;
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

正解:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>

using namespace std;

#ifdef unix
#define LL "%lld"
#else
#define LL "%I64d"
#endif

tm *s,*t;

int year,month,day,hour,minute,second;

int main() {
    freopen("two.in","r",stdin);
    freopen("two.out","w",stdout);

    scanf("%d-%d-%d %d:%d:%d",&year,&month,&day,&hour,&minute,&second);
    s=new tm();
    s->tm_year=year-1900;
    s->tm_mon=month-1;
    s->tm_mday=day;
    s->tm_hour=hour;
    s->tm_min=minute;
    s->tm_sec=second;

    scanf("%d-%d-%d %d:%d:%d",&year,&month,&day,&hour,&minute,&second);
    t=new tm();
    t->tm_year=year-1900;
    t->tm_mon=month-1;
    t->tm_mday=day;
    t->tm_hour=hour;
    t->tm_min=minute;
    t->tm_sec=second;
    printf(LL "
",(long long)fabs(difftime(mktime(s),mktime(t)))*1000);


    return 0;
}

T2 死亡

【问题描述】现在有M个位置可以打sif,有N+1个人在排队等着打sif。现在告诉你前N个人每个人需要多长时间打sif,问第n+1个人什么时候才能打sif(前N个人必须按顺序来)

【输入格式】

第一行两个整数N,M,如上所述。

接下来N行每行一个整数代表每个人所需要用的时间。

【输出格式】

一行一个整数表示答案。

【样例输入】

3 2

1

1

1

【样例输出】

1

【样例解释】

山里有座庙。

【数据规模与约定】

对于100%的数据,每个人所需要用的时间不超过10^5。

N小于等于100000 M小于等于50000

题解

考试:50分线段树模拟。

先求前m个人最小时间mint,ans+=mint,然后计算1--r(开始r为m)中有多少个人的时间减去Mint=0,说明这个人玩完啦,

然后统计有多少个人玩完了,r就向后挪几位..然后again重复。

正解:贪心+优先队列模拟 

再来的人去花费等待时间最少的那个人得位置。

代码

50分

#include<iostream>
#include<cstdio>
#define inf 0x7fffffff
using namespace std;

int n,m,ans,mint,js,rr,t[100005];
struct Tr{
    int l,r,mi;
}tr[400005];

void pushup(int rt){
    tr[rt].mi=min(tr[rt<<1].mi,tr[rt<<1|1].mi);
    return ;
}

void build(int rt,int l,int r){
    tr[rt].l=l;tr[rt].r=r;
    if(l==r){
        tr[rt].mi=t[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    pushup(rt);
}

int query(int rt,int l,int r){
    if(l<=tr[rt].l&&tr[rt].r<=r){
        return tr[rt].mi;
    }
    int mid=(tr[rt].l+tr[rt].r)>>1;
    if(r<=mid)return query(rt<<1,l,r);
    else if(l>mid)return query(rt<<1|1,l,r);
    else {
        return min(query(rt<<1,l,mid),query(rt<<1|1,mid+1,r));
    }
}

void update(int rt,int p,int q){
    if(tr[rt].l==tr[rt].r){
        if(tr[rt].l==p){
            if(tr[rt].mi!=inf)tr[rt].mi-=q;
            if(tr[rt].mi==0){
                js++;tr[rt].mi=inf;
            }
        }
        return ;
    }
    int mid=(tr[rt].l+tr[rt].r)>>1;
    if(p<=mid)update(rt<<1,p,q);
    else if(p>mid)update(rt<<1|1,p,q);
    pushup(rt);
}

int main(){
    freopen("death.in","r",stdin);
    freopen("death.out","w",stdout);
    scanf("%d%d",&n,&m);mint=inf;
    if(m>n){printf("0
");return 0;}
    for(int i=1;i<=n;i++){scanf("%d",&t[i]);mint=min(mint,t[i]);}
    if(n==m){printf("%d
",mint);return 0;}
    build(1,1,n);rr=m;
    while(1){
        int minn=query(1,1,rr);ans+=minn;
        js=0;
        for(int i=1;i<=rr;i++)update(1,i,minn);
        if(js>(n-rr)){
            printf("%d
",ans);
            return 0;
        }
        rr+=js;
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

AC代码

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,m,x;
priority_queue<int>q;
int main(){
    freopen("death.in","r",stdin);
    freopen("death.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&x);x*=-1;
        if(q.size()<m)q.push(x);
        else {
            int cur=q.top();
            q.pop();
            q.push(cur+x); 
        }
    }
    printf("%d
",q.top()*(-1));
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3 凝视

【问题描述】

背包是个好东西,希望我也有。

给你一个二维背包,它的体积是N*M,现在你有一些大小为1*2和1*3的物品,每个物品有自己的价值。

你希望往背包里面装一些无in,使得他们的价值和最大,问最大的价值和是多少。

【输入格式】

第一行一个整数T代表该测试点的数据数组。

对于每组数据,第一行有四个整数N,M,n1,n2,其中n1,n2分别代表大小为1*2和1*3的物品个数。

接下来一行有 n1个数代表每个1*2的物品的价值。

接下来一行有n2个数代表每个1*3物品的价值。

【输出格式】

对于每组询问,输出能够达到的价值的最大值。

【样例输入】

1

2 3 2 2

1 2

1 2

【样例输出】

4

【样例解释】

庙里有座山。

【数据规模与约定】

1≤T≤10,1≤N,M≤500,0≤n1,n2≤10000。

题解

//没看数据范围傻唧唧的写了个背包dp ╭(╯^╰)╮

正解 贪心

当背包2*2的方格时,虽然 2*2=4>1*3,似乎能再放下一个1*3的物品,但是实际上是放不下的。

我们枚举背包放1*3的物品的个数,O(1)求出1*2的物品的个数,但是如果具有上述特殊情况时,

虽然在大小上是能再放下一个1*3的物品,但实际上放不下的,需要特判。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;

int n,m,n1,n2,t,ans,max3;
int sum2[10005],sum3[10002],a[10002],b[10005];

bool cmp(int a,int b){return a>b;}

int main(){
    freopen("eyesight.in","r",stdin);
    freopen("eyesight.out","w",stdout);
    scanf("%d",&t);
    while(t--){
        ans=0;
        scanf("%d%d%d%d",&n,&m,&n1,&n2);
        for(int i=1;i<=n1;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n2;i++)scanf("%d",&b[i]);
        sort(a+1,a+n1+1,cmp);
        sort(b+1,b+n2+1,cmp);
        for(int i=1;i<=n1;i++)sum2[i]=sum2[i-1]+a[i];
        for(int i=1;i<=n2;i++)sum3[i]=sum3[i-1]+b[i];
        int vv=n*m;
        if((n==2||m==2)&&(m%3==2&&n%3==2))vv-=4;
        for(int i=0;i<=n2;i++){
            if(i*3>vv)break;
            int k2=(n*m-i*3)/2;
            ans=max(ans,sum2[min(k2,n1)]+sum3[i]);
        }
        printf("%d
",ans);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
原文地址:https://www.cnblogs.com/zzyh/p/7485217.html