#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; } |