#include<cstdio> #include<algorithm> #define debug(a) using namespace std; int grow[1000006]; //Tree typedef pair<long long, long long> para; para tab[1000006]; int MAXI; void init(int n) { MAXI = 1; while(MAXI < n) { MAXI*=2; } } para get(int i) { i = MAXI + i; para wyn = tab[i]; while(i > 0) { wyn = max(wyn, tab[i]); i /= 2; } return wyn; } void update(int x, int y, para co, int a, int b, int ter) { if(y < a || x > b) { return; } if(a >= x && b <= y) { tab[ter] = co; return; } int sr = (a+b)/2; update(x, y, co, a, sr, 2*ter); update(x, y, co, sr+1, b, 2*ter+1); } //end of tree //binserch bool IsLeft(long long current_time, long long height, int i) { debug(printf("sprawdzam %d\n", i)); para tmp = get(i); long long cut_time = tmp.first; long long prev_height = tmp.second; debug(printf("Na %d scinano o %lld do %lld\n", i, cut_time, prev_height)); long long current_height = prev_height + (current_time - cut_time)*grow[i]; return current_height >= height; } int binserch(long long t, long long h, int first, int last) { int sr = (first + last)/2; if(IsLeft(t,h,sr)) { if(!IsLeft(t, h, sr+1)) { return sr; } else { return binserch(t, h, sr+1, last); } } else { return binserch(t, h, first, sr-1); } } int find(long long int t, long long int h, int n) { if(!IsLeft(t, h, 0)) return -1; if(IsLeft(t, h, n-1)) return n-1; return binserch(t, h, 0, n-1); } //end binsearch long long int sufix[100006]; int heu(int n, int m) { init(n); for(int i = 0; i < n; i++) { scanf("%d", &grow[i]); } sort(grow, grow+n); reverse(grow, grow+n); sufix[n] = 0; for(int i = n-1; i >= 0; i--) { sufix[i] = sufix[i+1] + grow[i]; } long long int previous_time = 0; long long int prev = 0; for(int i =0; i < n; i++) { debug(printf("%d\n", grow[i])); } for(int i =0; i < m; i++) { long long int current_time; long long int h; scanf("%lld %lld", ¤t_time, &h); debug(printf("Nowy przypadek -- czas to %lld a wyskosc to %lld\n", current_time, h)); int end = find(current_time, h, n); debug(printf("znaleziony koniec to %d\n", end)); long long int dt = current_time - previous_time; debug(printf("przeszlo %lld czasu\n", dt)); long long int grow = sufix[0]*dt; debug(printf("z poprzedniego zostalo %lld\n", prev)); debug(printf("przyroslo %lld zielska\n", grow)); long long int left = (end+1)*h + sufix[end+1]*dt; debug(printf("po scienciu zostalo %lld\n", left)); printf("%lld\n", prev + grow - left); para cut(current_time, h); if(end != -1) { update(0, end, cut, 0, MAXI-1, 1); } prev = left; previous_time = current_time; } } long long int height[1000006]; int brut(int n, int m) { for(int i =0; i < n; i++) { scanf("%d", &grow[i]); } long long int prev_t = 0; for(int i =0; i < m; i++) { long long int t, h; scanf("%lld %lld", &t, &h); long long int dt = t - prev_t; long long int ans = 0; for(int i = 0; i < n; i++) { height[i] += grow[i]*dt; if(height[i] > h) { ans += height[i] - h; height[i] = h; } } prev_t = t; printf("%lld\n", ans); } return 0; } int main() { int n, m; scanf("%d %d", &n, &m); long long int k = n; k *= m; if(k < 1000000000) { brut(n,m); } else { heu(n,m); } }
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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #include<cstdio> #include<algorithm> #define debug(a) using namespace std; int grow[1000006]; //Tree typedef pair<long long, long long> para; para tab[1000006]; int MAXI; void init(int n) { MAXI = 1; while(MAXI < n) { MAXI*=2; } } para get(int i) { i = MAXI + i; para wyn = tab[i]; while(i > 0) { wyn = max(wyn, tab[i]); i /= 2; } return wyn; } void update(int x, int y, para co, int a, int b, int ter) { if(y < a || x > b) { return; } if(a >= x && b <= y) { tab[ter] = co; return; } int sr = (a+b)/2; update(x, y, co, a, sr, 2*ter); update(x, y, co, sr+1, b, 2*ter+1); } //end of tree //binserch bool IsLeft(long long current_time, long long height, int i) { debug(printf("sprawdzam %d\n", i)); para tmp = get(i); long long cut_time = tmp.first; long long prev_height = tmp.second; debug(printf("Na %d scinano o %lld do %lld\n", i, cut_time, prev_height)); long long current_height = prev_height + (current_time - cut_time)*grow[i]; return current_height >= height; } int binserch(long long t, long long h, int first, int last) { int sr = (first + last)/2; if(IsLeft(t,h,sr)) { if(!IsLeft(t, h, sr+1)) { return sr; } else { return binserch(t, h, sr+1, last); } } else { return binserch(t, h, first, sr-1); } } int find(long long int t, long long int h, int n) { if(!IsLeft(t, h, 0)) return -1; if(IsLeft(t, h, n-1)) return n-1; return binserch(t, h, 0, n-1); } //end binsearch long long int sufix[100006]; int heu(int n, int m) { init(n); for(int i = 0; i < n; i++) { scanf("%d", &grow[i]); } sort(grow, grow+n); reverse(grow, grow+n); sufix[n] = 0; for(int i = n-1; i >= 0; i--) { sufix[i] = sufix[i+1] + grow[i]; } long long int previous_time = 0; long long int prev = 0; for(int i =0; i < n; i++) { debug(printf("%d\n", grow[i])); } for(int i =0; i < m; i++) { long long int current_time; long long int h; scanf("%lld %lld", ¤t_time, &h); debug(printf("Nowy przypadek -- czas to %lld a wyskosc to %lld\n", current_time, h)); int end = find(current_time, h, n); debug(printf("znaleziony koniec to %d\n", end)); long long int dt = current_time - previous_time; debug(printf("przeszlo %lld czasu\n", dt)); long long int grow = sufix[0]*dt; debug(printf("z poprzedniego zostalo %lld\n", prev)); debug(printf("przyroslo %lld zielska\n", grow)); long long int left = (end+1)*h + sufix[end+1]*dt; debug(printf("po scienciu zostalo %lld\n", left)); printf("%lld\n", prev + grow - left); para cut(current_time, h); if(end != -1) { update(0, end, cut, 0, MAXI-1, 1); } prev = left; previous_time = current_time; } } long long int height[1000006]; int brut(int n, int m) { for(int i =0; i < n; i++) { scanf("%d", &grow[i]); } long long int prev_t = 0; for(int i =0; i < m; i++) { long long int t, h; scanf("%lld %lld", &t, &h); long long int dt = t - prev_t; long long int ans = 0; for(int i = 0; i < n; i++) { height[i] += grow[i]*dt; if(height[i] > h) { ans += height[i] - h; height[i] = h; } } prev_t = t; printf("%lld\n", ans); } return 0; } int main() { int n, m; scanf("%d %d", &n, &m); long long int k = n; k *= m; if(k < 1000000000) { brut(n,m); } else { heu(n,m); } } |