#include <cstdio> #include <vector> #include <algorithm> using namespace std; typedef long long int LL; struct Node{ LL ilosc=0; LL sumaWysokosci=0; LL sumaPrzyrostow=0; LL minWysokosc=0,maxWysokosc=0; LL minPrzyrost=0,maxPrzyrost=0;//for computing minmax wysokosc after growing LL deferredSciecie=-1;//if not -1 we want to cut it deferred LL ostatnieOdwiedziny=0;//when it should've been cut, to compute przyrost Node* left=nullptr; Node* right=nullptr; void initH(LL h){ ilosc=1; sumaWysokosci=0; sumaPrzyrostow = h; minWysokosc = maxWysokosc = 0; minPrzyrost = maxPrzyrost = h; } void initParent(Node* l, Node* r){ left=l; right=r; sumaPrzyrostow = l->sumaPrzyrostow+r->sumaPrzyrostow; ilosc = l->ilosc+r->ilosc; sumaWysokosci=0;//at start we can probably assume this if(r->sumaPrzyrostow>=0){ minWysokosc = min(l->minWysokosc,r->minWysokosc); minPrzyrost = min(l->minPrzyrost,r->minPrzyrost); }else{//if right isn't initalized, we just consider left minWysokosc = l->minWysokosc; minPrzyrost = l->minPrzyrost; } maxWysokosc = max(l->maxWysokosc,r->maxWysokosc); maxPrzyrost = max(l->maxPrzyrost,r->maxPrzyrost); } void update(){ sumaWysokosci = left->sumaWysokosci+right->sumaWysokosci; if(right->sumaPrzyrostow>=0){//it's not empty minWysokosc = min(left->minWysokosc,right->minWysokosc); minPrzyrost = min(left->minPrzyrost,right->minPrzyrost); }else{//if right isn't initalized, we just consider left minWysokosc = left->minWysokosc; minPrzyrost = left->minPrzyrost; } maxWysokosc = max(left->maxWysokosc,right->maxWysokosc); maxPrzyrost = max(left->maxPrzyrost,right->maxPrzyrost); } void zetnij(LL height){ //skoro scinamy, tzn. że wszystkie były wyższe, stąd teraz wszystkie są równe height, więc: maxWysokosc = height;//min(maxWysokosc,height); minWysokosc = height;//min(minWysokosc,height); sumaWysokosci = ilosc*height; } void computePrzyrosty(LL t){ if(deferredSciecie!=-1){ zetnij(deferredSciecie); if(left!=nullptr){ left->deferredSciecie = deferredSciecie; left->ostatnieOdwiedziny = ostatnieOdwiedziny; right->deferredSciecie = deferredSciecie; right->ostatnieOdwiedziny = ostatnieOdwiedziny; } deferredSciecie=-1; } LL dt = t-ostatnieOdwiedziny; minWysokosc+=minPrzyrost*dt; maxWysokosc+=maxPrzyrost*dt; sumaWysokosci+=sumaPrzyrostow*dt; ostatnieOdwiedziny = t; } LL cut(LL czas, LL scinamyDo){ computePrzyrosty(czas); if(maxWysokosc<=scinamyDo) return 0; if(minWysokosc>scinamyDo){ //scinamy wszystkie //mamy aktualną wysokość //liczymy przyrost z różnicy LL sumaWynikowa = ilosc*scinamyDo; minWysokosc = scinamyDo; maxWysokosc = scinamyDo; LL przyrost = sumaWysokosci-sumaWynikowa;//tyle zostało ścięte //prLLf("(%d-%d)\n",sumaWysokosci,sumaWynikowa); sumaWysokosci = sumaWynikowa; //i zapuszczamy deferred if(left!=nullptr){ left->deferredSciecie=scinamyDo; left->ostatnieOdwiedziny=czas; right->deferredSciecie=scinamyDo; right->ostatnieOdwiedziny=czas; } return przyrost; }else{//partial (on border), so go deeper LL l=left->cut(czas,scinamyDo),r=right->cut(czas,scinamyDo); //prLLf("{%d+%d}\n",l,r); update(); return l+r; //return left->cut(czas,scinamyDo)+right->cut(czas,scinamyDo); } } }; vector<Node> drzewo; int main(){ LL n,m; scanf("%lld%lld",&n,&m); vector<LL> pola(n); for(LL i=0;i<n;++i){ scanf("%lld",&pola[i]); } sort(pola.begin(),pola.end()); LL potega = 1; while(potega<n) potega<<=1; drzewo.resize(2*potega+1); for(LL i=0;i<n;++i) drzewo[potega+i].initH(pola[i]); for(LL i=potega-1;i>=1;--i) drzewo[i].initParent(&drzewo[2*i],&drzewo[2*i+1]); Node* root = &drzewo[1]; for(LL i=0;i<m;++i){ LL t,h; scanf("%lld%lld",&t,&h); //prLLf("Suma %d\n",root->sumaWysokosci); printf("%lld\n",root->cut(t,h)); } }
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #include <cstdio> #include <vector> #include <algorithm> using namespace std; typedef long long int LL; struct Node{ LL ilosc=0; LL sumaWysokosci=0; LL sumaPrzyrostow=0; LL minWysokosc=0,maxWysokosc=0; LL minPrzyrost=0,maxPrzyrost=0;//for computing minmax wysokosc after growing LL deferredSciecie=-1;//if not -1 we want to cut it deferred LL ostatnieOdwiedziny=0;//when it should've been cut, to compute przyrost Node* left=nullptr; Node* right=nullptr; void initH(LL h){ ilosc=1; sumaWysokosci=0; sumaPrzyrostow = h; minWysokosc = maxWysokosc = 0; minPrzyrost = maxPrzyrost = h; } void initParent(Node* l, Node* r){ left=l; right=r; sumaPrzyrostow = l->sumaPrzyrostow+r->sumaPrzyrostow; ilosc = l->ilosc+r->ilosc; sumaWysokosci=0;//at start we can probably assume this if(r->sumaPrzyrostow>=0){ minWysokosc = min(l->minWysokosc,r->minWysokosc); minPrzyrost = min(l->minPrzyrost,r->minPrzyrost); }else{//if right isn't initalized, we just consider left minWysokosc = l->minWysokosc; minPrzyrost = l->minPrzyrost; } maxWysokosc = max(l->maxWysokosc,r->maxWysokosc); maxPrzyrost = max(l->maxPrzyrost,r->maxPrzyrost); } void update(){ sumaWysokosci = left->sumaWysokosci+right->sumaWysokosci; if(right->sumaPrzyrostow>=0){//it's not empty minWysokosc = min(left->minWysokosc,right->minWysokosc); minPrzyrost = min(left->minPrzyrost,right->minPrzyrost); }else{//if right isn't initalized, we just consider left minWysokosc = left->minWysokosc; minPrzyrost = left->minPrzyrost; } maxWysokosc = max(left->maxWysokosc,right->maxWysokosc); maxPrzyrost = max(left->maxPrzyrost,right->maxPrzyrost); } void zetnij(LL height){ //skoro scinamy, tzn. że wszystkie były wyższe, stąd teraz wszystkie są równe height, więc: maxWysokosc = height;//min(maxWysokosc,height); minWysokosc = height;//min(minWysokosc,height); sumaWysokosci = ilosc*height; } void computePrzyrosty(LL t){ if(deferredSciecie!=-1){ zetnij(deferredSciecie); if(left!=nullptr){ left->deferredSciecie = deferredSciecie; left->ostatnieOdwiedziny = ostatnieOdwiedziny; right->deferredSciecie = deferredSciecie; right->ostatnieOdwiedziny = ostatnieOdwiedziny; } deferredSciecie=-1; } LL dt = t-ostatnieOdwiedziny; minWysokosc+=minPrzyrost*dt; maxWysokosc+=maxPrzyrost*dt; sumaWysokosci+=sumaPrzyrostow*dt; ostatnieOdwiedziny = t; } LL cut(LL czas, LL scinamyDo){ computePrzyrosty(czas); if(maxWysokosc<=scinamyDo) return 0; if(minWysokosc>scinamyDo){ //scinamy wszystkie //mamy aktualną wysokość //liczymy przyrost z różnicy LL sumaWynikowa = ilosc*scinamyDo; minWysokosc = scinamyDo; maxWysokosc = scinamyDo; LL przyrost = sumaWysokosci-sumaWynikowa;//tyle zostało ścięte //prLLf("(%d-%d)\n",sumaWysokosci,sumaWynikowa); sumaWysokosci = sumaWynikowa; //i zapuszczamy deferred if(left!=nullptr){ left->deferredSciecie=scinamyDo; left->ostatnieOdwiedziny=czas; right->deferredSciecie=scinamyDo; right->ostatnieOdwiedziny=czas; } return przyrost; }else{//partial (on border), so go deeper LL l=left->cut(czas,scinamyDo),r=right->cut(czas,scinamyDo); //prLLf("{%d+%d}\n",l,r); update(); return l+r; //return left->cut(czas,scinamyDo)+right->cut(czas,scinamyDo); } } }; vector<Node> drzewo; int main(){ LL n,m; scanf("%lld%lld",&n,&m); vector<LL> pola(n); for(LL i=0;i<n;++i){ scanf("%lld",&pola[i]); } sort(pola.begin(),pola.end()); LL potega = 1; while(potega<n) potega<<=1; drzewo.resize(2*potega+1); for(LL i=0;i<n;++i) drzewo[potega+i].initH(pola[i]); for(LL i=potega-1;i>=1;--i) drzewo[i].initParent(&drzewo[2*i],&drzewo[2*i+1]); Node* root = &drzewo[1]; for(LL i=0;i<m;++i){ LL t,h; scanf("%lld%lld",&t,&h); //prLLf("Suma %d\n",root->sumaWysokosci); printf("%lld\n",root->cut(t,h)); } } |