#include #define ll long long #define pb push_back using namespace std; int N, FR, ALG; ll B, S = 1e18, P[1000500], H[1000500], R = 1, sum[1000500], psum[1000500]; struct stick { ll h; ll p; int order; }A[1000500]; vector TS[1000500]; vector VS[1000500]; vector V; vector VW; clock_t start, finish; mt19937_64 rng; void CLEARF() { for(int i = 1; i <= FR; i++) VS[i].clear(); } void CLEART() { for(int i = 1; i <= R; i++) sum[i] = 0; for(int i = 1; i <= R; i++) TS[i].clear(); R = 1; } void REPLACE() { CLEARF(); FR = R; for(int i = 1; i <= R; i++) for(int j = 0; j < TS[i].size(); j++) VS[i].pb(TS[i][j]); CLEART(); } bool TScmp(int a, int b) { return TS[a].size() < TS[b].size(); } bool revcmp(stick a, stick b) { return a.h > b.h; } bool cmp1(stick a, stick b) { return a.h < b.h; } bool cmp(stick a, stick b) { if(float(a.h) / float(b.h) < 1.1 and float(a.h) / float(b.h) > 0.9) return a.p > b.p; else return a.h < b.h; } bool cmp2(stick a, stick b) { return a.p < b.p; } bool cmp3(stick a, stick b) { return a.p > b.p; } void FINAL_OUT() { printf("%d\n", FR); for(int i = 1; i <= FR; i++) { printf("%d ", VS[i].size()); for(int j = 0; j < VS[i].size(); j++) printf("%d ", VS[i][j]); printf("\n"); } } void TEST_OUT() { printf("%d\n", R); for(int i = 1; i <= R; i++) { printf("Rupa %d[%lld] %d ", i, sum[i], TS[i].size()); for(int j = 0; j < TS[i].size(); j++) printf("ID %d Height %lld Penalty %lld;", TS[i][j], H[TS[i][j]], P[TS[i][j]]); printf("\n"); } } void MIN() { for(int i = 1; i <= R; i++) { int k = TS[i].size() - 1; int m = k; ll mini = 1e18; if(sum[i] <= B) continue; for(int j = 0; j < TS[i].size(); j++) { if(P[TS[i][j]] < mini and sum[i] - H[TS[i][j]] < B) { mini = P[TS[i][j]]; m = j; } } if(m != k) swap(TS[i][m], TS[i][k]); } return; } void WORK0() { for(int i = 1; i <= N; i++) { stick pom; pom = A[i]; VW.pb(A[i]); } sort(VW.begin(), VW.end(), revcmp); vector ::iterator it = VW.begin(); while(VW.size()) { stick pom = VW[0]; VW.erase(VW.begin()); sum[R] += pom.h; psum[R] += pom.p; TS[R].pb(pom.order); if(sum[R] < B and VW.size()) { while(sum[R] < B and VW.size()) { stick temp; temp.h = B - sum[R] - 1; it = lower_bound(VW.begin(), VW.end(), temp, revcmp); // printf("%lld\n", it->h); if(it == VW.end() or sum[R] + it->h >= B) break; sum[R] += it->h; psum[R] += it->p; temp.order = it->order; TS[R].pb(temp.order); VW.erase(it); } if(VW.size()) R++; } else { if(VW.size()) R++; } } int k = 1; for(int i = R; i; i--) { if(k + TS[i].size() >= i) break; if(psum[i] < R * R * R - (R - 1) * (R - 1) * (R - 1)) { while(TS[i].size()) { if (k >= i) break; if(sum[k] < B) { TS[k].pb(TS[i].back()); sum[k] += H[TS[i].back()]; TS[i].pop_back(); } k++; } R--; } else break; } // TEST_OUT(); } void WORK2() { // printf("DRUGI\n"); for(int i = 1; i <= N; i++) { sum[R] += A[i].h; if(sum[R] > B and i < N) { if(sum[R] - A[i].h > B or !TS[R].size() or A[i].h >= B) { TS[R].pb(A[i].order); R++; } else if((R + 1) * (R + 1) * (R + 1) - R * R * R < A[i].p) { sum[R] -= A[i].h; R++; TS[R].pb(A[i].order); sum[R] = A[i].h; } else { TS[R].pb(A[i].order); R++; } } else if(sum[R] == B and i < N) { TS[R].pb(A[i].order); R++; } else TS[R].pb(A[i].order); } } void WORK3() { // printf("TRECI\n"); int cnt = 0; V.clear(); R = 1; // for(int i = 1; i <= N; i++) // printf("%d ", A[i].order); // printf("\n"); for(int i = 1; i <= N - cnt; i++) { sum[R] += A[i].h; if(sum[R] < B or (sum[R] == B and i + cnt == N)) TS[R].pb(A[i].order); else if(sum[R] == B or !TS[R].size() or A[i].h >= B) { TS[R].pb(A[i].order); R++; } else { sum[R] -= A[i].h; V.pb(R); cnt++; // printf("i = %d, cnt = %d\n", i, cnt); if(i + cnt > N and cnt <= R) break; R++; TS[R].pb(A[i].order); sum[R] = A[i].h; } } int k = N - cnt; // printf("k = %d\n", k); // printf("RUPE "); // for(int i = 0; i < V.size(); i++) // printf("%d ", V[i]); // printf("\n"); // TEST_OUT(); int v = V.size(); int i = 0; while(i < v) { k++; if((R + 1) * (R + 1) * (R + 1) - R * R * R < A[k].p and A[k].h < B) { R++; while(sum[R] < B and k <= N) { // printf("k = %d\n", k); // printf("A[k].order = %d\n", A[k].order); sum[R] += A[k].h; TS[R].pb(A[k].order); k++; } k--; } else { // printf("A[k].order = %d\n", A[k].order); TS[V[i]].pb(A[k].order); sum[V[i]] += A[k].h; i++; } if(k == N) break; } V.clear(); } int MIN_SCORE(int x) { MIN(); ll score = R * R * R; for(int i = 1; i <= R; i++) { if(sum[i] > B) { int j = TS[i].size() - 1; score += P[TS[i][j]]; } } if(score < S) { ALG = x; S = score; printf("ALG = %d R = %lld Score = %lld\n", ALG, R, score); return 1; } else return 0; } int SCORE(int x) { ll score = R * R * R; for(int i = 1; i <= R; i++) { if(sum[i] > B) { // printf("PENALTY\n"); int j = TS[i].size() - 1; score += P[TS[i][j]]; } } if(score < S) { ALG = x; S = score; printf("ALG = %d R = %lld Score = %lld\n", ALG, R, score); return 1; } else return 0; } void IN() { freopen("sticks.in", "r", stdin); scanf("%d%lld", &N, &B); for(int i = 1; i <= N; i++) { scanf("%lld", &A[i].h); H[i] = A[i].h; } for(int i = 1; i <= N; i++) { scanf("%lld", &A[i].p); P[i] = A[i].p; } for(int i = 1; i <= N; i++) A[i].order = i; } void OUT() { freopen("sticks.out", "w", stdout); printf("%d\n", FR); for(int i = 1; i <= FR; i++) { printf("%d ", VS[i].size()); for(int j = 0; j < VS[i].size(); j++) printf("%d ", VS[i][j]); printf("\n"); } } void DO() { WORK2(); if(MIN_SCORE(2) == 1) REPLACE(); else CLEART(); WORK3(); if(MIN_SCORE(3) == 1) REPLACE(); else CLEART(); } void SOLVE() { start = clock(); if(N <= 10000) { WORK0(); if(SCORE(0) == 1) REPLACE(); else CLEART(); } printf("------------------------------ Iteracija I\n"); DO(); printf("------------------------------ Iteracija II\n"); sort(A + 1, A + N + 1, cmp); DO(); printf("------------------------------ Iteracija III\n"); sort(A + 1, A + N + 1, cmp3); DO(); printf("------------------------------ Iteracija IV\n"); sort(A + 1, A + N + 1, cmp1); DO(); for(int i = 1; i <= 10000000; i++) { finish = clock(); if((finish - start) / CLOCKS_PER_SEC > 3.5) break; shuffle(A + 1, A + N + 1, rng); DO(); } printf("FINAL SCORE = %lld\nRUPA %d\n", S, FR); printf("ALGORITAM %d\n", ALG); // FINAL_OUT(); } int main() { rng.seed(time(NULL)); IN(); SOLVE(); OUT(); return 0; }