#include <cstdio>
#include <algorithm>
const int MAXN = 500007;
long long szybkosc[MAXN], przyciecieIndeks[MAXN], przyciecieDzien[MAXN], przyciecieWysokosc[MAXN], sumaSzybkosci[MAXN];
int ilePrzyciec;
long long obliczWysokosc(long long dzien, int indeks) {
int start = std::lower_bound(przyciecieIndeks, przyciecieIndeks + ilePrzyciec, indeks) - przyciecieIndeks;
if (przyciecieIndeks[start] > indeks)
start--;
long long wysokosc = przyciecieWysokosc[start];
long long dni = dzien - przyciecieDzien[start];
return dni * szybkosc[indeks] + wysokosc;
}
int main() {
int pole, koszenia, poczatek;
long long dzien, poziom;
scanf("%d%d", &pole, &koszenia);
for (int i = 0; i < pole; i++)
scanf("%lld", &szybkosc[i]);
std::sort(szybkosc, szybkosc + pole);
sumaSzybkosci[0] = 0;
for (int i = 1; i <= pole + 1; i++) {
sumaSzybkosci[i] = sumaSzybkosci[i - 1] + szybkosc[i - 1];
}
poczatek = 0;
ilePrzyciec = 1;
przyciecieIndeks[ilePrzyciec] = pole;
for (int i = 0; i < koszenia; i++) {
scanf("%lld%lld", &dzien, &poziom);
int lewy = 0, prawy = pole;
while (lewy < prawy) {
int srodek = (lewy + prawy) / 2;
if (obliczWysokosc(dzien, srodek) < poziom)
lewy = srodek + 1;
else
prawy = srodek;
}
int start = std::lower_bound(przyciecieIndeks, przyciecieIndeks + ilePrzyciec, lewy) - przyciecieIndeks;
long long skoszona = 0;
int poprzedni = start;
if (przyciecieIndeks[start] > lewy)
poprzedni--;
if (lewy < pole) {
skoszona += (przyciecieIndeks[poprzedni + 1] - lewy) * przyciecieWysokosc[poprzedni];
skoszona += (sumaSzybkosci[przyciecieIndeks[poprzedni + 1]] - sumaSzybkosci[lewy]) * (dzien - przyciecieDzien[poprzedni]);
while (poprzedni < ilePrzyciec - 1) {
poprzedni++;
skoszona += (przyciecieIndeks[poprzedni + 1] - przyciecieIndeks[poprzedni]) * przyciecieWysokosc[poprzedni];
skoszona += (sumaSzybkosci[przyciecieIndeks[poprzedni + 1]] - sumaSzybkosci[przyciecieIndeks[poprzedni]])
* (dzien - przyciecieDzien[poprzedni]);
}
skoszona -= (pole - lewy) * poziom;
przyciecieIndeks[start] = lewy;
przyciecieWysokosc[start] = poziom;
przyciecieDzien[start] = dzien;
przyciecieIndeks[start + 1] = pole;
przyciecieWysokosc[start + 1] = 0;
przyciecieDzien[start + 1] = 0;
ilePrzyciec = start + 1;
}
printf("%lld\n", skoszona);
}
return 0;
}
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 | #include <cstdio> #include <algorithm> const int MAXN = 500007; long long szybkosc[MAXN], przyciecieIndeks[MAXN], przyciecieDzien[MAXN], przyciecieWysokosc[MAXN], sumaSzybkosci[MAXN]; int ilePrzyciec; long long obliczWysokosc(long long dzien, int indeks) { int start = std::lower_bound(przyciecieIndeks, przyciecieIndeks + ilePrzyciec, indeks) - przyciecieIndeks; if (przyciecieIndeks[start] > indeks) start--; long long wysokosc = przyciecieWysokosc[start]; long long dni = dzien - przyciecieDzien[start]; return dni * szybkosc[indeks] + wysokosc; } int main() { int pole, koszenia, poczatek; long long dzien, poziom; scanf("%d%d", &pole, &koszenia); for (int i = 0; i < pole; i++) scanf("%lld", &szybkosc[i]); std::sort(szybkosc, szybkosc + pole); sumaSzybkosci[0] = 0; for (int i = 1; i <= pole + 1; i++) { sumaSzybkosci[i] = sumaSzybkosci[i - 1] + szybkosc[i - 1]; } poczatek = 0; ilePrzyciec = 1; przyciecieIndeks[ilePrzyciec] = pole; for (int i = 0; i < koszenia; i++) { scanf("%lld%lld", &dzien, &poziom); int lewy = 0, prawy = pole; while (lewy < prawy) { int srodek = (lewy + prawy) / 2; if (obliczWysokosc(dzien, srodek) < poziom) lewy = srodek + 1; else prawy = srodek; } int start = std::lower_bound(przyciecieIndeks, przyciecieIndeks + ilePrzyciec, lewy) - przyciecieIndeks; long long skoszona = 0; int poprzedni = start; if (przyciecieIndeks[start] > lewy) poprzedni--; if (lewy < pole) { skoszona += (przyciecieIndeks[poprzedni + 1] - lewy) * przyciecieWysokosc[poprzedni]; skoszona += (sumaSzybkosci[przyciecieIndeks[poprzedni + 1]] - sumaSzybkosci[lewy]) * (dzien - przyciecieDzien[poprzedni]); while (poprzedni < ilePrzyciec - 1) { poprzedni++; skoszona += (przyciecieIndeks[poprzedni + 1] - przyciecieIndeks[poprzedni]) * przyciecieWysokosc[poprzedni]; skoszona += (sumaSzybkosci[przyciecieIndeks[poprzedni + 1]] - sumaSzybkosci[przyciecieIndeks[poprzedni]]) * (dzien - przyciecieDzien[poprzedni]); } skoszona -= (pole - lewy) * poziom; przyciecieIndeks[start] = lewy; przyciecieWysokosc[start] = poziom; przyciecieDzien[start] = dzien; przyciecieIndeks[start + 1] = pole; przyciecieWysokosc[start + 1] = 0; przyciecieDzien[start + 1] = 0; ilePrzyciec = start + 1; } printf("%lld\n", skoszona); } return 0; } |
English