Contest-hunter 暑假送温暖 SRM01

一直找不到好的题去做...于是想到了srm...回来补题...QAQ

从srm01补起

A

题意:n个数,排成一列,刚开始都是1,如果左右相等就可以合并,问最后的数列长什么样。

思路:比赛的时候直接敲了个 一直log2 直到为0,觉得应该是100的...于是炸到了90.

比完赛懒得调就没去理,回来补的时候发现是p的trunc有点问题哇...以后都打成trunc(x+0.000001) 出错率会低一点QAQ

1 var n,s:longint;
2 begin
3   read(n);
4   repeat
5     s:=trunc(ln(n)/ln(2)+0.00001);
6     write(s+1,' ');
7     n:=n-(1 << s);
8   until n=0;
9 end.
A

B

题意:有m升油,n个数,可以用一升油数某一个数+1,再给一个mx 然后给 v1 v2 求 (v1*达到mx的数的个数+v2*整个数列的最小值)最大化。

思路:比赛的时候想的是拿部分分,然后弄不出来,然后觉得是二分,敲不出来,就拿到了10分。

补题的时候有一个新的思路,枚举达到mx的数的个数,然后再二分最小值。

然后check就贪心的弄,设达到mx的数的个数为num,二分到的最小值为x

然后贪心算需要的油就可以check了,但是这样要多一个n的复杂度。

显然o(n^2 logn)的复杂度是要tle的。

想想优化,由于贪心,所以已经先把原数列排序了,辣么就满足的单调性。

满足单调性就可以二分

所以求排序后的数列的前缀和,然后在二分里在套一个二分就好了

复杂度 o(n logn ^2)

 1 var a,b,c,sum:array[0..200000]of int64;
 2     n,mx,v1,v2:int64;
 3     have,z:int64;
 4     l,r,m:longint;
 5     ans,num,ansmin,ansnum:int64;
 6     i,j:longint;
 7 procedure qs(l,r:longint);
 8 var i,j,t,m:longint;
 9 begin
10   i:=l;
11   j:=r;
12   m:=a[(l+r)>>1];
13   repeat
14     while a[i]>m do inc(i);
15     while a[j]<m do dec(j);
16     if i<=j then
17     begin
18       t:=a[i];a[i]:=a[j];a[j]:=t;
19       t:=c[i];c[i]:=c[j];c[j]:=t;
20       inc(i);
21       dec(j);
22     end;
23   until i>j;
24   if l<j then qs(l,j);
25   if i<r then qs(i,r);
26 end;
27 function find(x:longint):longint;
28 var l,r,m:longint;
29 begin
30   l:=num+1;
31   r:=n;
32   while l<=r do
33   begin
34     m:=(l+r) >>1;
35     if a[m]>x then l:=m+1 else r:=m-1;
36   end;
37   exit(l);
38 end;
39 function check(x:longint):boolean;
40 var i:longint;
41     need:int64;
42 begin
43   need:=z;
44   i:=find(x);
45   inc(need,x*(n-i+1)-(sum[n]-sum[i-1]));
46   if need>have then exit(false) else exit(true);
47 end;
48 begin
49   read(n,mx,v1,v2,have);
50   for i:=1 to n do
51   begin
52     read(a[i]);
53     b[i]:=a[i];
54     c[i]:=i;
55   end;
56   qs(1,n);
57   for i:=1 to n do
58   sum[i]:=sum[i-1]+a[i];
59   for i:=1 to n do
60   begin
61     num:=i;
62     z:=mx*num-sum[num];
63     if z>=have then continue;
64     l:=1;
65     r:=mx;
66     while l<r do
67     begin
68       m:=(l+r+1)>>1;
69       if check(m) then l:=m else r:=m-1;
70     end;
71     if ans<num*v1+l*v2 then
72     begin
73       ans:=num*v1+l*v2;
74       ansnum:=num;
75       ansmin:=l;
76     end;
77   end;
78   writeln(ans);
79   for i:=1 to ansnum do
80   b[c[i]]:=mx;
81   for i:=1 to n do
82   if b[i]<ansmin then write(ansmin,' ')else write(b[i],' ');
83   writeln;
84 end.
B

C

题意:一个数列,支持两个操作,1.L~R 加上x   2.查询当前序列,如果从任意一个位置开始,两边严格递减的最大长度。

思路:比赛的时候完全没思路,暴力都不会打。

补题觉得可以线段树弄,每次维护区间最大长度,左边的值,右边的值,然后乱维护....QAQ

结果不会打。所以pass掉吧...

 

posted @ 2017-08-08 18:13  Bunnycxk  阅读(247)  评论(2编辑  收藏  举报