前言
嘛现在或许晚了点。。。水题的时候兴致一来就顺手切了(嘛也不是随手
嗯,就这样
题解
T1 标题统计
题目描述
凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?
注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。
不想多说什么,特别得水捏,遍历一遍就差不多了
Var s:string[10];
tot,i:longint;
Begin
readln(s);
tot:=0;
for i:=1 to length(s) do
Begin
if s[i] in ['A'..'Z','a'..'z','0'..'9'] then
Begin
inc(tot);
end;
end;
write(tot);
end.
T2 龙虎斗
题目描述
暴力一遍把
位工兵放置在每个位置,使得差距最小化
Var n,m,p1,s1,s2,tot1,tot2,disparity,temp,pos,deposit:int64;
i:longint;
c:array[1..100005] of int64;
Begin
readln(n);
for i:=1 to n do
Begin
read(c[i]);
end;
readln(m,p1,s1,s2);
c[p1]:=c[p1]+s1;
for i:=1 to m-1 do
Begin
tot1:=tot1+c[i]*(m-i);
end;
for i:=m+1 to n do
Begin
tot2:=tot2+c[i]*(i-m);
end;
disparity:=abs(tot2-tot1);
deposit:=disparity;
for i:=1 to m-1 do
Begin
temp:=abs(tot2-(tot1+s2*(m-i)));
if temp<disparity then
Begin
disparity:=temp;
pos:=i;
end;
end;
for i:=m+1 to n do
Begin
temp:=abs(tot2+s2*(i-m)-tot1);
if temp<disparity then
Begin
disparity:=temp;
pos:=i;
end;
end;
if disparity=deposit then
Begin
write(m);
end
else
Begin
write(pos);
end;
end.
T3 摆渡车
题目描述
有 ? 名同学要乘坐摆渡车从人大附中前往人民大学,第 ? 位同学在第 ?? 分钟去等车。只有一辆摆渡车在工作,但摆渡车容量可以视为无限大。摆渡车从人大附中出发、把车上的同学送到人民大学、再回到人大附中(去接其他同学),这样往返一趟总共花费 ? 分钟(同学上下车时间忽略不计)。摆渡车要将所有同学都送到人民大学。
凯凯很好奇,如果他能任意安排摆渡车出发的时间,那么这些同学的等车时间之和最小为多少呢?
注意:摆渡车回到人大附中后可以即刻出发。
dalao说可以用斜率优化,但是嘛没必要
我承认我不会斜率优化…
很显然,状态转移方程为:
其中
为第直至
个时间点的人数和
表示至
的最小等待时间
于是乎很快就可推出核心程序:
for (int i=0;i<time+m;i++){
f[i]=tot[i]*i-sum[i];
int ST=fmax(i-2*m+1,0);
for (int j=ST;j<=i-m;j++){
f[i]=fmin(f[i],f[j]+(tot[i]-tot[j])*i-(sum[i]-sum[j]));
}
}
for(int i=time;i<time+m;i++){
minAns=minAns<f[i]?minAns:f[i];
}
但是时间复杂度显然是超出了限制,
那么这段程序如何优化呢,
其实很容易就可以想到,这么长的一条时间轴,只有
个点是需要取的,况且这些点中还有不少是重合的,由此可得知这些点是离散得十分严重的,那么的话如果把所有的点都遍历一遍显然是不可取的。
那么这就需要加上一个判断了:当当前的
到
中没有人的话,把
的状态转移到
即可
AC完整代码:
#include<cstdio>
#include<cmath>
using namespace std;
int t[505],tot[4000005],sum[4000005],f[4000005];
int n,m,time=0;
int minAns=2147483647;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&t[i]);
tot[t[i]]++;
sum[t[i]]+=t[i];
time=fmax(time,t[i]);
}
for(int i=1;i<time+m;i++){
tot[i]+=tot[i-1];
sum[i]+=sum[i-1];
}
for(int i=0;i<time+m;i++){
if (i>=m&&tot[i-m]==tot[i]){
f[i]=f[i-m];
continue;
}
f[i]=tot[i]*i-sum[i];
int ST=fmax(i-2*m+1,0);
for(int j=ST;j<=i-m;j++){
f[i]=fmin(f[i],f[j]+(tot[i]-tot[j])*i-(sum[i]-sum[j]));
}
}
for(int i=time;i<time+m;i++){
minAns=minAns<f[i]?minAns:f[i];
}
printf("%d",minAns);
return 0;
}
T4 对称二叉树
题目描述
如果暴力遍历来判断两个子树
和
是否对称,最坏的情况下要遍历
个点。
按照轻链的性质可以分析出总复杂度为
故暴力搜索即可
附上代码:
uses math;
Var n,i,j,ans:longint;
weight,temp:array[1..1000005] of longint;
Sub:array[1..1000005] of record
left,right:longint;
end;
Function get_validity(x,y,z:longint):boolean;
Begin
if weight[y]=weight[z] then
Begin
if (Sub[y].left*Sub[z].right<0) or (Sub[y].right*Sub[z].left<0) then
Begin
exit(false);
end
else if ((Sub[y].left=-1) or (get_validity(x,Sub[y].left,Sub[z].right))) and ((Sub[y].right=-1) or (get_validity(x,Sub[y].right,Sub[z].left))) then
Begin
exit(true);
end;
end;
exit(false);
end;
Procedure get_total(x:longint);
Begin
if Sub[x].left<>-1 then
Begin
get_total(Sub[x].left);
temp[x]:=temp[Sub[x].left];
end;
if Sub[x].right<>-1 then
Begin
get_total(Sub[x].right);
temp[x]:=temp[x]+temp[Sub[x].right];
end;
temp[x]:=temp[x]+1;
end;
Begin
readln(n);
for i:=1 to n do read(weight[i]);
for i:=1 to n do read(Sub[i].left,Sub[i].right);
get_total(1);
ans:=1;
for i:=1 to n do
Begin
if (Sub[i].left<>-1) and (Sub[i].right<>-1) and (get_validity(i,Sub[i].left,Sub[i].right)) then
Begin
ans:=max(temp[i],ans);
end;
end;
write(ans);
end.