A. Saitama Destroys Hotel
【题意】一楼梯从最高层开始依次下降,每下一层花1s,如果该层有人,则等乘客到达后载客继续下降,乘客进电梯的时间忽略不计,给定有乘客的楼层数及乘客到达时间,求承载所有乘客下至第0层所花费的最小时间。
【代码】
#include<iostream>
using namespace std;
int main (void)
{
int n,s;
int minutes=0;
int f[1005],t[1005];
cin>>n>>s;
for(int i=0;i<n;i++){
cin>>f[i]>>t[i];
}
f[n]=s;
for(int i=n-1;i>=0;i--){
minutes+=f[i+1]-f[i];
if(minutes<t[i]) minutes=t[i];
}
cout<<minutes+f[0]<<endl;
return 0;
}
B. Hamming Distance Sum
【题意】给定两个字符串a,b,求b中所有跟a长度相同的子串中,各个字符与a中相应字符的差的绝对值的和。
【分析】对于字符串b中每个字符,记录该字符之前包含该字符在内的子串中0,1出现的次数。对于长度为lena的字符串a,长度为lenb的字符串b,a中第i个字符可以与b中第i到第lenb-lena+i个字符进行比较。若a中字符为0,则最后结果加上该区间内的字符为1的字符个数,若为1,则加上字符为0的个数。
【代码】
#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=200005;
char a[maxn],b[maxn];
int main (void)
{
cin>>a>>b;
int lena=strlen(a);
int lenb=strlen(b);
long long r=0;
int d1[maxn],d0[maxn];
r=0;
for(int i=0;i<lenb;i++){
d0[i]=d0[i-1];
d1[i]=d1[i-1];
if(b[i]=='0') d0[i]++;
else d1[i]++;
}
for(int i=0;i<lena;i++){
if(a[i]=='0')r+=d1[lenb-lena+i]-d1[i-1];
else r+=d0[lenb-lena+i]-d0[i-1];
}
cout<<r<<endl;
return 0;
}
C. Chain Reaction
【题意】一连串灯塔,从左到右排列,位于位置a[i]的灯塔,激活后,可以破坏距离为b[i]范围内的其他灯塔,灯塔仅可向左边攻击,攻击他人自己不受损坏,受损的灯塔不能被再次激活。 现在整个排列的最右边放置一个灯塔,使得从右向左依次激活灯塔后,受破坏的灯塔个数最少。
【分析】激活最右边的灯塔之后,所有被破坏的灯塔中距离激活的灯塔最远的灯塔左边的灯塔得以存活,所以从左向右依次记录激活该灯塔后,左边剩余灯塔个数,算出最大值,用总灯塔数减去该最大值。
【代码】
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
int m[1000005];
int dp[1000005];
int main (void)
{
int n;
cin>>n;
int x,y;
int mins=0x3ffffff;
int maxn=0;
for(int i = 0; i < n; i++){
cin>>x>>y;
m[x]=y;
mins=min(mins,x);
maxn=max(maxn,x);
}
for(int i = mins; i <= maxn; i++){
if(!m[i]) {dp[i]=dp[i-1]; continue;}
if(i-m[i]-1>=0) dp[i]=dp[i-m[i]-1]+1;
else dp[i]=1;
}
long long ans=0;
for(int i = mins; i <= maxn; i++){
if(ans<dp[i]) ans=dp[i];
}
cout<<n-ans<<endl;
return 0;
}