1
- // Ivan Carvalho
2
- // Solution to https://dmoj.ca/problem/apio10p1
3
- #include < cstdio>
4
- #include < algorithm>
5
- #include < vector>
6
- using namespace std ;
7
- typedef long long ll;
8
- vector<ll> M,B;
9
- int pointer;
10
- bool bad (int l1,int l2,int l3)
11
- {
12
- /*
13
- intersection(l1,l2) has x-coordinate (b1-b2)/(m2-m1)
14
- intersection(l1,l3) has x-coordinate (b1-b3)/(m3-m1)
15
- set the former greater than the latter, and cross-multiply to
16
- eliminate division
17
- */
18
- return (B[l3]-B[l1])*(M[l1]-M[l2])<(B[l2]-B[l1])*(M[l1]-M[l3]);
19
- }
20
- // Adds a new line (with lowest slope) to the structure
21
- void add (long long m,long long b)
22
- {
23
- // First, let's add it to the end
24
- m *= -1 ;
25
- b *= -1 ;
26
- M.push_back (m);
27
- B.push_back (b);
28
- // If the penultimate is now made irrelevant between the antepenultimate
29
- // and the ultimate, remove it. Repeat as many times as necessary
30
- while (M.size ()>=3 &&bad (M.size ()-3 ,M.size ()-2 ,M.size ()-1 ))
31
- {
32
- M.erase (M.end ()-2 );
33
- B.erase (B.end ()-2 );
34
- }
35
- }
36
- // Returns the minimum y-coordinate of any intersection between a given vertical
37
- // line and the lower envelope
38
- long long query (long long x)
39
- {
40
- // If we removed what was the best line for the previous query, then the
41
- // newly inserted line is now the best for that query
42
- if (pointer>=M.size ())
43
- pointer=M.size ()-1 ;
44
- // Any better line must be to the right, since query values are
45
- // non-decreasing
46
- while (pointer<M.size ()-1 &&
47
- M[pointer+1 ]*x+B[pointer+1 ]<M[pointer]*x+B[pointer])
48
- pointer++;
49
- return -(M[pointer]*x+B[pointer]);
50
- }
51
- int main (){
52
- int TC = 1 ;
53
- while (TC--){
54
- M.clear ();
55
- B.clear ();
56
- pointer = 0 ;
57
- int n;
58
- scanf (" %d" ,&n);
59
- ll a,b,c;
60
- scanf (" %lld %lld %lld" ,&a,&b,&c);
61
- add (0LL ,0LL );
62
- ll davez, soma = 0 ;
63
- for (int i=1 ;i<n;i++){
64
- scanf (" %lld" ,&davez);
65
- soma += davez;
66
- ll best = query (soma) + a*soma*soma + b*soma + c;
67
- add (-2 *a*soma,best + a*soma*soma - b*soma);
68
- }
69
- scanf (" %lld" ,&davez);
70
- soma += davez;
71
- ll best = query (soma) + a*soma*soma + b*soma + c;
72
- printf (" %lld\n " ,best);
73
- }
74
- return 0 ;
75
- }n 0 ;
76
- }
1
+ // Ivan Carvalho
2
+ // Solution to https://dmoj.ca/problem/apio10p1
3
+ #include < cstdio>
4
+ #include < algorithm>
5
+ #include < vector>
6
+ using namespace std ;
7
+ typedef long long ll;
8
+ vector<ll> M,B;
9
+ int pointer;
10
+ bool bad (int l1,int l2,int l3)
11
+ {
12
+ /*
13
+ intersection(l1,l2) has x-coordinate (b1-b2)/(m2-m1)
14
+ intersection(l1,l3) has x-coordinate (b1-b3)/(m3-m1)
15
+ set the former greater than the latter, and cross-multiply to
16
+ eliminate division
17
+ */
18
+ return (B[l3]-B[l1])*(M[l1]-M[l2])<(B[l2]-B[l1])*(M[l1]-M[l3]);
19
+ }
20
+ // Adds a new line (with lowest slope) to the structure
21
+ void add (long long m,long long b)
22
+ {
23
+ // First, let's add it to the end
24
+ m *= -1 ;
25
+ b *= -1 ;
26
+ M.push_back (m);
27
+ B.push_back (b);
28
+ // If the penultimate is now made irrelevant between the antepenultimate
29
+ // and the ultimate, remove it. Repeat as many times as necessary
30
+ while (M.size ()>=3 &&bad (M.size ()-3 ,M.size ()-2 ,M.size ()-1 ))
31
+ {
32
+ M.erase (M.end ()-2 );
33
+ B.erase (B.end ()-2 );
34
+ }
35
+ }
36
+ // Returns the minimum y-coordinate of any intersection between a given vertical
37
+ // line and the lower envelope
38
+ long long query (long long x)
39
+ {
40
+ // If we removed what was the best line for the previous query, then the
41
+ // newly inserted line is now the best for that query
42
+ if (pointer>=M.size ())
43
+ pointer=M.size ()-1 ;
44
+ // Any better line must be to the right, since query values are
45
+ // non-decreasing
46
+ while (pointer<M.size ()-1 &&
47
+ M[pointer+1 ]*x+B[pointer+1 ]<M[pointer]*x+B[pointer])
48
+ pointer++;
49
+ return -(M[pointer]*x+B[pointer]);
50
+ }
51
+ int main (){
52
+ int TC = 1 ;
53
+ while (TC--){
54
+ M.clear ();
55
+ B.clear ();
56
+ pointer = 0 ;
57
+ int n;
58
+ scanf (" %d" ,&n);
59
+ ll a,b,c;
60
+ scanf (" %lld %lld %lld" ,&a,&b,&c);
61
+ add (0LL ,0LL );
62
+ ll davez, soma = 0 ;
63
+ for (int i=1 ;i<n;i++){
64
+ scanf (" %lld" ,&davez);
65
+ soma += davez;
66
+ ll best = query (soma) + a*soma*soma + b*soma + c;
67
+ add (-2 *a*soma,best + a*soma*soma - b*soma);
68
+ }
69
+ scanf (" %lld" ,&davez);
70
+ soma += davez;
71
+ ll best = query (soma) + a*soma*soma + b*soma + c;
72
+ printf (" %lld\n " ,best);
73
+ }
74
+ return 0 ;
75
+ }
0 commit comments