1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdint>
#include <stack>

using namespace std;


struct ciecie
{public:
    int64_t d,b;
    ciecie() : d(0),b(0){};
    ciecie (int64_t d_, int64_t b_) : d(d_),b(b_){};
};

struct koszenie
{
    ciecie ciach;
    int index;
    koszenie (int64_t d_, int64_t b_, int index_): ciach{d_,b_},index(index_) {};
    koszenie (ciecie ciach_, int index_): ciach{ciach_},index(index_) {};
};

vector<int64_t> a;
vector<int64_t> cumsum;

int64_t wysokosc ( const koszenie &kosz, const int64_t czas )
{
    return (czas-kosz.ciach.d)*a[kosz.index] + kosz.ciach.b;
}

int main()
{
    ios_base::sync_with_stdio(false);

    int m,n;
    cin>>n>>m;

    a=vector<int64_t>(n,0);
    cumsum = vector<int64_t>(n+1,0);


    for (int i=0;i<n;i++)
         cin>>a[i];

    sort(begin(a),end(a));

    for (int i=n-1;i>=0 ;i--)
        cumsum[i]=a[i]+cumsum[i+1];

    vector<ciecie> cuts(m);

    for (int i=0;i<m;i++)
    {
         cin>>cuts[i].d;
         cin>>cuts[i].b;
    }

    stack <koszenie> koszenia;

    koszenia.push( koszenie{0,0,0} );

    for (vector<ciecie>::iterator itcut = begin(cuts); itcut !=end(cuts); ++itcut )
    {
        int i, last_i=n;
        int64_t t = itcut->d;
        int64_t c = itcut->b;
        int64_t skoszono =0;
        while (!koszenia.empty() && wysokosc(koszenia.top(),t)> c )
        {
            koszenie kosz = koszenia.top();
            i=kosz.index;
            skoszono += (kosz.ciach.b-c)*(last_i-i) + (cumsum[i]-cumsum[last_i])*(t-kosz.ciach.d);

            koszenia.pop();
            last_i = i;
        }

        if (!koszenia.empty())
        {
            //wysokosc[i] = a[i]*(t-d) + b > c
            //pstatni, ktory nie zostanie skoszony
            //a[i]*(t-d) + b  = c
            //a[i] = ((c - b) / (t-d) )
            koszenie kosz = koszenia.top();
            int64_t  a_cel= (c  - kosz.ciach.b )/(t-kosz.ciach.d); //najwiekszy przyrost, który nie da skoszenia.
            auto it_a = upper_bound( begin(a)+kosz.index , begin(a)+last_i, a_cel );
            i = it_a-begin(a);

            skoszono += (cumsum[i]-cumsum[last_i])*(t-kosz.ciach.d) +(kosz.ciach.b-c)*(last_i-i);
        }
        if (skoszono>0)
            koszenia.push( koszenie{*itcut,i} );
        cout<<skoszono<<endl;

    }
    return 0;
}