济南-1029试题解题报告
By shenben
本解题报告解析均为100分解题思路。
上午
T1
题意:给你两个日期,问这两个日期差了多少毫秒
解析:标程用ctime库函数写的,编译器版本高了才会过(NOIP编译器版本不会太高);
只能老老实实打模拟。
小技巧:最后多输出“000”,计算秒就好了。(特判两个时间相同,只输出“0”)
T2
题意:有m个站口,有n个人按顺序排队,求n+1个人最少等多长时间
解析:(标程显然 同下)
①n<m 输出0(显然)
②n>=m 建一个小根堆(可以用优先队列),把前m个人的时间扔到堆里
贪心策略:每次都放在用时较短的人的后面
每次取出堆顶t,删掉堆顶,把(当前时间+t)再扔到堆里。循环n-m次
最后输出堆顶(就是答案)。
T3
题意:一个n*m的场地,有n1个1*2的砖,有n2个1*3的砖,每一块砖都有一定的价值,求可以铺下的最大价值。
解析:
解法一:基于连通性的状态压缩dp(不会)
解法二:贪心
预处理出前缀和
sa[i]表示前i大的1*2的砖的价值和是sa[i];
sb[i]表示前i大的1*3的砖的价值和是sb[i];
先铺1*3的砖,对应1*2的砖的数目可求,那么本次价值t 用O(1)的时间 可求
0->n*m/3扫一遍 ans=max(ans,t);
输出ans。
注意:要特判n*m=2*2,2*5……的情况
以2*2为例,只能放两块1*2的砖,1*3的一块也放不了
下午
T1
题意:(祖玛游戏)给你一个只包含ABC的串,m次操作,每次在p位置,插入c字符,输出每次操作后的字符串。
脑补:
祖玛游戏 每次射击一个字符,若>=3个相同的连在一起,即可消去。消去后,两边的珠子像空隙靠拢、相连,若还有>=3个相同的连在一起,再次消去。
但,若初始有>=3个相同的连在一起,不击打当前位置,依旧不会消除。
解析:
手动打模拟。
T2
题意:n个元素按顺序进栈,求字典序最大的出栈序列。
解析:
贪心策略:
1、压到n,n出栈,输出n
2、如果后面有大于栈内元素的(这里可以用RMQ维护一下),继续压栈;
否则,出栈,输出当前元素。(对栈内每一个元素都操作)
3、输出栈内剩余的元素
T3
题意:给n条线段,m次询问,每次一个p点的坐标,求线段OP 与n条线段会产生多少个交点
解析:
题目保证任意两条线段不相交,说明n条线段任意两两互相平行,即n条线段的斜率均为k。
那么,先配对,再排序,再二分答案。
求出op与当前线段的交点。若交点在横坐标在(0,x1)&&纵坐标在(0,y1),则线段op与当前线段有交点,即为合法解。否则,….
二分出op最远可与线段x有交点,则当先询问有x个交点(当前询问的答案)。
上午
T1代码:
#include<cstdio> #include<cstring> #include<ctime> #include<iostream> #define ll long long using namespace std; int mth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; ll solve(){ int Y=0,M=0,D=0,h=0,m=0,s=0; scanf("%d-%d-%d %d:%d:%d",&Y,&M,&D,&h,&m,&s); Y-=2000; ll ans=365*Y; ans+=(Y+3)/4; for(int i=1;i<M;i++) ans+=mth[i]; ans+=(!(Y%4)&&M>2)?1:0; ans+=D; ans*=86400; ans+=(h*60+m)*60+s; return ans; } int main(){ freopen("two.in","r",stdin); freopen("two.out","w",stdout); ll s1=solve(); ll s2=solve(); printf("%I64d%s ",s2-s1,s2-s1?"000":""); return 0; }
std版(不一定会过)
#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代码:
#include<cstdio> #include<iostream> #include<queue> #include<vector> #define ll long long #ifdef unix #define LL "%lld" #else #define LL "%I64d" #endif using namespace std; const int N=1e5+10; priority_queue<ll,vector<ll>,greater<ll> >q; ll n,m,a[N]; inline const ll read(){ register ll x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int main(){ freopen("death.in","r",stdin); freopen("death.out","w",stdout); n=read();m=read(); for(ll i=1;i<=n;i++) a[i]=read(); for(ll i=1;i<=m;i++) q.push(a[i]); for(ll t,i=m+1;i<=n;i++){ t=q.top();q.pop(); q.push(t+a[i]); } ll ans=q.top(); printf(LL,ans); return 0; }
T3代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int N=1e5+10; int T,n,m,n1,n2,a[N],b[N]; int delta,ans,sa[N],sb[N]; 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,greater<int>()); sort(b+1,b+n2+1,greater<int>()); for(int i=1;i<=n1;i++) sa[i]=sa[i-1]+a[i]; for(int i=1;i<=n2;i++) sb[i]=sb[i-1]+b[i]; /*不严密的特判 if(n==2&&m==2){ printf("%d ",sa[2]); continue; } if((n==2&&m==5)||(n==5&&m==2)){ int t1=sb[2]+sa[2]; int t2=sb[1]+sa[3]; int t3=sa[5]; printf("%d ",max(t1,max(t1,t2))); continue; }*/ delta=((n%3==2&&m%3==2)&&(n==2||m==2))?4:n*m%3; int v=n*m; int v1=min((v-delta)/3,n2); for(int j,i=0;i<=v1;i++){ j=(v-i*3)>>1; if(j>n1) j=n1; ans=max(ans,sb[i]+sa[j]); } printf("%d ",ans); } fclose(stdin); fclose(stdout); return 0; }
下午
T1代码:
#include<cstdio> #include<iostream> #include<cstring> #define name "ha" using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } inline const char in(){ for(register char ch=getchar();;ch=getchar()) if(ch>='A'&&ch<='Z') return ch; } const int N=1e4+10; char a[N]; int n,cas; char c; int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); gets(a+1);//注意空串 n=strlen(a+1); cas=read(); for(int i=0,pos,l,r;i<cas;i++){ pos=read();c=in(); for(int i=n+1;i>=pos+2;i--) a[i]=a[i-1]; n++; a[pos+1]=c; for(;;){ for(l=pos;(l>=1)&&(a[l]==a[pos+1]);l--) continue; for(r=pos+2;(r<=n)&&(a[r]==a[pos+1]);r++) continue; int len=r-l-1; if(len>=3){ pos=l;n-=len; for(int i=pos+1;i<=n;i++) a[i]=a[i+len]; for(int i=n+1;i<=n+len;i++) a[i]=0; a[n+1]=0; } else break; } if(n==0) printf("- "); else printf("%s ",a+1); } return 0; }
T2代码:
#include<cstdio> #include<iostream> #include<string> #include<cmath> #define name "haha" using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int N=1e6+10; int n,a[N]; int top,s[N]; int f[N][21]; short vis[N]; inline void RMQ(){ for(int i=1;i<=n;i++) f[i][0]=a[i]; for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]); } } } inline int query(int i,int j){ int k=log(j-i+1)/log(2); return max(f[i][k],f[j-(1<<k)+1][k]); } int main(){ freopen(name".in","r",stdin); freopen(name".out","w",stdout); n=read(); int now=n; for(int i=1;i<=n;i++) a[i]=read(); RMQ(); for(int i=1,mz;i<=n;i++){ s[++top]=a[i]; vis[a[i]]=1; if(i==n) break; mz=query(i+1,n); if(mz>s[top]) continue; for(;s[top]==now&&now&⊤){ printf("%d ",s[top]); vis[s[top]]=0; now--;top--; } if(s[top+1]==now+1){ /*mz=query(i+1,n); if(mz>s[top]) continue;*/ for(;vis[now]&&s[top]>mz&&now&⊤top--){ printf("%d ",s[top]);vis[s[top]]=0; if(s[top]==now&&top) now--; } for(;s[top]>mz&⊤top--) printf("%d ",s[top]),vis[s[top]]=0; } for(;s[top]>mz&⊤top--) printf("%d ",s[top]),vis[s[top]]=0; } for(;top;top--) printf("%d ",s[top]); return 0; }
T3代码:
#include<cstdio> #include<algorithm> #define DB double #define name "hahaha" using namespace std; inline const int read(){ register int x=0,f=1; register char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } const int N=2e5+10; int n,m,X[N],Y[N]; DB B[N],K[N]; bool check(DB x1,DB y1,int mid){ if(K[mid]*x1+B[mid]>y1) return 0; return 1; } int main(){ freopen("hahaha.in","r",stdin); freopen("hahaha.out","w",stdout); n=read(); for(int i=1;i<=n;i++) X[i]=read(); for(int i=1;i<=n;i++) Y[i]=read(); sort(X+1,X+n+1);sort(Y+1,Y+n+1); for(int i=1;i<=n;i++){ B[i]=(DB)Y[i]; K[i]=-(DB)Y[i]/(DB)X[i]; } m=read(); for(int i=1,x,y;i<=m;i++){ x=read();y=read(); int l=1,r=n,mid,ans=0; while(l<=r){ mid=l+r>>1; if(check(x,y,mid)) ans=mid,l=mid+1; else r=mid-1; } printf("%d ",ans); } return 0; }
补发题目:
P73
竞赛时间:????年??月??日??:??-??:??
题目名称 |
第二题 |
死亡 |
凝视 |
名称 |
two |
death |
eyesight |
输入 |
two.in |
death.in |
eyesight.in |
输出 |
two.out |
death.out |
eyesight.out |
每个测试点时限 |
1秒 |
1秒 |
1秒 |
内存限制 |
512MB |
512MB |
512MB |
测试点数目 |
10 |
10 |
10 |
每个测试点分值 |
10 |
10 |
10 |
是否有部分分 |
无 |
无 |
无 |
题目类型 |
传统 |
传统 |
传统 |
注意事项(请务必仔细阅读):
第二题
【题目描述】
给你两个日期,问这两个日期差了多少毫秒。
【输入格式】
两行,每行一个日期,日期格式保证为“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
【样例解释】
从前有座山。
【数据范围与规定】
对于的数据,两个日期相同。
对于的数据,两个日期只有秒数可能不同。
对于的数据,两个日期只有秒数、分钟数可能不同。
对于的数据,两个日期的年月日一定相同。
对于的数据,两个日期的年月一定相同。
对于的数据,两个日期的年份一定相同。
对于的数据,两个日期一定都是21世纪的某一天,且第二个日期一定大于等于第一个日期。
死亡
【问题描述】
现在有个位置可以打sif,有个人在排队等着打sif。现在告诉你前个人每个人需要多长的时间打sif,问你第个人什么时候才能打sif。(前个人必须按照顺序来)
【输入格式】
第一行两个整数如上所述。
接下来行每行一个整数代表每个人所需要用的时间。
【输出格式】
一行一个整数表示答案。
【样例输入】
3 2
1
1
1
【样例输出】
1
【样例解释】
山里有座庙。
【数据规模与约定】
对于的数据,每个人所需用的时间不超过。
测试点 |
|
|
测试点 |
|
|
1 |
10 |
10 |
1 |
5000 |
500 |
2 |
20 |
10 |
2 |
100000 |
5000 |
3 |
50 |
10 |
3 |
100000 |
10000 |
4 |
1000 |
500 |
4 |
100000 |
20000 |
5 |
2000 |
500 |
5 |
100000 |
50000 |
凝视
【问题描述】
背包是个好东西,希望我也有。
给你一个二维的背包,它的体积是。现在你有一些大小为和的物品,每个物品有自己的价值。你希望往背包里面装一些物品,使得它们的价值和最大,问最大的价值和是多少。
【输入格式】
第一行一个整数代表该测试点的数据组数。
对于每组数据,第一行有四个整数,其中分别代表大小为和大小为的物品个数。
接下来一行有个数代表每个物品的价值。
接下来一行有个数代表每个物品的价值。
【输出格式】
对于每组询问,输出能够达到的价值最大值。
【样例输入】
1
2 3 2 2
1 2
1 2
【样例输出】
4
【样例解释】
庙里有座山。
【数据规模与约定】
对于的数据,。
对于的数据,。
对于的数据,。
P74
竞赛时间:????年??月??日??:??-??:??
题目名称 |
|
|
|
名称 |
ha |
haha |
hahaha |
输入 |
ha.in |
haha.in |
hahaha.in |
输出 |
ha.out |
haha.out |
hahaha.out |
每个测试点时限 |
1秒 |
1.5秒 |
1.5秒 |
内存限制 |
512MB |
512MB |
512MB |
测试点数目 |
10 |
10 |
10 |
每个测试点分值 |
10 |
10 |
10 |
是否有部分分 |
无 |
无 |
无 |
题目类型 |
传统 |
传统 |
传统 |
注意事项(请务必仔细阅读):
【问题描述】
祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。
开发商最近准备为玩家写一个游戏过程的回放工具。他们已经在游戏内完成了过程记录的功能,而回放功能的实现则委托你来完成。
游戏过程的记录中,首先是轨道上初始的珠子序列,然后是玩家接下来所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。
【输入格式】
第一行是一个由大写字母'A'~'Z'组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。
第二行是一个数字,表示整个回放过程共有次操作。
接下来的行依次对应于各次操作。每次操作由一个数字和一个大写字母描述,以空格分隔。其中,为新珠子的颜色。若插入前共有颗珠子,则表示新珠子嵌入之后(尚未发生消除之前)在轨道上的位序。
【输出格式】
输出共行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上的珠子序列。
如果轨道上已没有珠子,则以“-”表示。
【样例输入】
ACCBA
5
1 B
0 A
2 B
4 C
0 A
【样例输出】
ABCCBA
AABCCBA
AABBCCBA
-
A
【样例解释】
你以为山里又有座庙?
【数据规模与约定】
的数据满足。
【问题描述】
栈是一种强大的数据结构,它的一种特殊功能是对数组进行排序。例如,借助一个栈,依次将数组1,3,2按顺序入栈或出栈,可对其从大到小排序:
1入栈;3入栈;3出栈;2入栈;2出栈;1出栈。
在上面这个例子中,出栈序列是3,2,1,因此实现了对数组的排序。
遗憾的是,有些时候,仅仅借助一个栈,不能实现对数组的完全排序。例如给定数组2,1,3,借助一个栈,能获得的字典序最大的出栈序列是3,1,2:
2入栈;1入栈;3入栈;3出栈;1出栈;2出栈。
请你借助一个栈,对一个给定的数组按照出栈顺序进行从大到小排序。当无法完全排序时,请输出字典序最大的出栈序列。
【输入格式】
输入共行。
第一行包含一个整数,表示入栈序列长度。
第二行包含个整数,表示入栈序列。输入数据保证给定的序列是到n的全排列,即不会出现重复数字。
【输出格式】
仅一行,共个整数,表示你计算出的出栈序列。
【样例输入】
3
2 1 3
【样例输出】
3 1 2
【样例解释】
这回山里有座塔。
【数据规模与约定】
对于的数据,。
对于的数据,。
对于的数据,。
【问题描述】
小Q对计算几何有着浓厚的兴趣。他经常对着平面直角坐标系发呆,思考一些有趣的问题。今天,他想到了一个十分有意思的题目:
首先,小Q会在轴正半轴和轴正半轴分别挑选个点。随后,他将轴的点与轴的点一一连接,形成条线段,并保证任意两条线段不相交。小Q确定这种连接方式有且仅有一种。最后,小Q会给出个询问。对于每个询问,将会给定一个点,请回答线段OP与条线段会产生多少个交点?
小Q找到了正在钻研数据结构的你,希望你可以帮他解决这道难题。
【输入格式】
第行包含一个正整数,表示线段的数量;
第行包含个正整数,表示小Q在轴选取的点的横坐标;
第行包含个正整数,表示小Q在轴选取的点的纵坐标;
第4行包含一个正整数,表示询问数量;
随后行,每行包含两个正整数,表示询问中给定的点的横、纵坐标。
【输出格式】
共行,每行包含一个非负整数,表示你对这条询问给出的答案。
【样例输入】
3
4 5 3
3 5 4
2
1 1
3 3
【样例输出】
0
3
【样例解释】
然后塔里啥都没有。
【数据规模与约定】
对于的数据,。
对于的数据,,坐标范围。