2016.07.16【初中部 NOIP提高组 】模拟赛C题解
2016-08-14 07:33
288 查看
题目:https://jzoj.net/senior/#contest/problems/1753
T1:
第一题就是一个数学题目而已,只要懂得∑这个符号的意思,以及有良好的思维即可AC。贴一下最难的一段的就是Yij的:
for i:=1 to n do
begin
for j:=1 to 8 do
begin
ans:=0;
for k:=1 to n do
ans:=ans+abs(sum[k,j]-avg[j]);
if ans=0 then
y[i,j]:=0
else
y[i,j]:=(sum[i,j]-avg[j])/(ans/n);
end;
end;T2:
第二题很明显是二分,二分答案。刚开始看题以为是DP,可以看看n的范围还是算了。二分最短的时间,假设最短时间为x,然后对于每个衣服a[i]-烘干值*x,最后看看x的时间够不够用(自己思考,差不多就是每个div一下的意思),够则缩,反之则扩。注意r的范围尽量弄大一点也没关系,不然可能爆0。
while l<r do
begin
mid:=(l+r) div 2;
if pd(mid) then
begin
r:=mid;
if mid<min then min:=mid;
end
else
l:=mid+1;
end;T3:
第三题考试的时候想到了暴力和二分,可惜二分不会实现。讲完题后我同桌proking也实现了许久。讲题时,一位神犇告诉了我们一个非常厉害的算法。
例如数据是:1,2,3,4,5,我们就把他复制一次,就是1,2,3,4,5,1,2,3,4,5。很明显,最大和为1-5这个序列的和15,注意是原序列。然后我们设一个队列,一旦队列的总和大于15的一半,就开始删掉队头的元素。最后的结果就是每次删完后队列最大的总和。
for i:=1 to 2*n do
begin
inc(len);
s:=s+a[i];
while s>ans div 2 do
begin
dec(len);
dec(s,a[l]);
inc(l);
end;
if s>max then max:=s;
if s=ans div 2 then break;
end;T4:
注意,题目的意思是,选取开头和结尾,期间的数,要大于开头,小于结尾,可以无顺序。据说这道题班上没人想出正解。但是有人想出了O(n^n)水过,数据小没办法。不过还是加了许多优化的。枚举起点,设一个max,表示当前队列中最大(终点)值为多少,往下搜,如果此点>max,则设此点为终点,这样保证了队列终点最大。
for i:=n downto 2 do
begin
min:=a[i];
for j:=i downto 1 do
begin
if a[j]>a[i] then break;
if (a[j]<min)or((j=i)and(a[j]<min)) then
begin
ans:=j;
min:=a[j];
end;
end;
if (i-ans+1>max)and(ans<>0) then max:=i-ans+1;
end;总结:
这次考得很差,该做的题目没做对,主要是数学能力和题目理解能力不太强,今后急需改正
T1:
第一题就是一个数学题目而已,只要懂得∑这个符号的意思,以及有良好的思维即可AC。贴一下最难的一段的就是Yij的:
for i:=1 to n do
begin
for j:=1 to 8 do
begin
ans:=0;
for k:=1 to n do
ans:=ans+abs(sum[k,j]-avg[j]);
if ans=0 then
y[i,j]:=0
else
y[i,j]:=(sum[i,j]-avg[j])/(ans/n);
end;
end;T2:
第二题很明显是二分,二分答案。刚开始看题以为是DP,可以看看n的范围还是算了。二分最短的时间,假设最短时间为x,然后对于每个衣服a[i]-烘干值*x,最后看看x的时间够不够用(自己思考,差不多就是每个div一下的意思),够则缩,反之则扩。注意r的范围尽量弄大一点也没关系,不然可能爆0。
while l<r do
begin
mid:=(l+r) div 2;
if pd(mid) then
begin
r:=mid;
if mid<min then min:=mid;
end
else
l:=mid+1;
end;T3:
第三题考试的时候想到了暴力和二分,可惜二分不会实现。讲完题后我同桌proking也实现了许久。讲题时,一位神犇告诉了我们一个非常厉害的算法。
例如数据是:1,2,3,4,5,我们就把他复制一次,就是1,2,3,4,5,1,2,3,4,5。很明显,最大和为1-5这个序列的和15,注意是原序列。然后我们设一个队列,一旦队列的总和大于15的一半,就开始删掉队头的元素。最后的结果就是每次删完后队列最大的总和。
for i:=1 to 2*n do
begin
inc(len);
s:=s+a[i];
while s>ans div 2 do
begin
dec(len);
dec(s,a[l]);
inc(l);
end;
if s>max then max:=s;
if s=ans div 2 then break;
end;T4:
注意,题目的意思是,选取开头和结尾,期间的数,要大于开头,小于结尾,可以无顺序。据说这道题班上没人想出正解。但是有人想出了O(n^n)水过,数据小没办法。不过还是加了许多优化的。枚举起点,设一个max,表示当前队列中最大(终点)值为多少,往下搜,如果此点>max,则设此点为终点,这样保证了队列终点最大。
for i:=n downto 2 do
begin
min:=a[i];
for j:=i downto 1 do
begin
if a[j]>a[i] then break;
if (a[j]<min)or((j=i)and(a[j]<min)) then
begin
ans:=j;
min:=a[j];
end;
end;
if (i-ans+1>max)and(ans<>0) then max:=i-ans+1;
end;总结:
这次考得很差,该做的题目没做对,主要是数学能力和题目理解能力不太强,今后急需改正
相关文章推荐
- {小结}2016.07.16【初中部 NOIP提高组 】模拟赛B
- 2016.07.16【初中部 NOIP提高组 】模拟赛C总结
- 2016.07.16【初中部 NOIP提高组 】模拟赛C
- 2016.07.16【初中部 NOIP提高组 】模拟赛C
- 2016.07.16【初中部 NOIP提高组 】模拟赛C
- 【初中部 NOIP提高组 】模拟赛A
- 2016.12.03【初中部 NOIP提高C组】模拟赛
- 2016.08.12【初中部 NOIP提高组 】模拟赛C
- 2016.08.17【初中部 NOIP提高组 】模拟赛C题解
- 2017.1.15【初中部 NOIP提高组】模拟赛B组
- 2016.09.03【初中部 NOIP提高组 】模拟赛A总结
- 2016.09.03【初中部 NOIP提高组 】模拟赛C题解
- 2016.09.10【初中部 NOIP提高组 】模拟赛C题解
- 2016.10.06【初中部 NOIP提高组 】模拟赛C
- 2016.10.29【初中部 NOIP提高组 】模拟赛C题解
- 2016.6.11【初中部 NOIP提高组 】模拟赛C
- 2016.07.07【初中部 NOIP提高组 】模拟赛C
- 2016.07.15【初中部 NOIP提高组 】模拟赛C
- 2016.09.24【初中部 NOIP提高组 】模拟赛C
- 2016.09.15【初中部 NOIP提高组 】模拟赛C