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",n,y,r,s,f,m); // printf("%d %d %d %d %d %d\n",nn,yy,rr,ss,ff,mm); if(n==nn&&y==yy&&r==rr&&s==ss&&f==ff&&m==mm){ printf("0\n");return 0; } if(n==nn&&y==yy&&r==rr&&s==ss&&f==ff&&m!=mm){ printf("%d\n",(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\n",(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 "\n",(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\n");return 0;} for(int i=1;i<=n;i++){scanf("%d",&t[i]);mint=min(mint,t[i]);} if(n==m){printf("%d\n",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\n",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\n",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\n",ans); } fclose(stdin); fclose(stdout); return 0; }