#include <iostream> #include <algorithm> #include <vector> #include <stack> using namespace std; vector<int> breakpoints; unsigned currentBreakpoints; int BST(int start, int end, int val) { if (start == end) { return start; } int mid = (start + end) / 2; if (breakpoints[mid] < val) { return BST(mid + 1, end, val); } else { return BST(start, mid, val); } } int getNextBreakpointPos(int val) { return BST(0, currentBreakpoints - 1, val); } int main() { ios_base::sync_with_stdio(0); int n, a; const long long p = 1000000007; long long *howMany; int *partialSums; int *values; cin >> n; partialSums = new int[n]; values = new int[n]; for (int i = 0; i < n; ++i) { cin >> a; values[i] = a; } sort(values, values + n); partialSums[0] = 0; for (int i = 0; i < n; ++i) { partialSums[i] = partialSums[i - 1] + values[i - 1]; } howMany = new long long[partialSums[n - 1] + 1]; for (int i = 0; i < partialSums[n - 1] + 1; ++i) { howMany[i] = 0; } stack<pair<int, long long>> howManyToAdd; breakpoints.push_back(0); breakpoints.push_back(partialSums[n - 1] + 1); for (int i = n - 1; i >= 0; --i) { // cout << "processing " << i << endl; currentBreakpoints = breakpoints.size(); if (i == n - 1) { howMany[values[i] - 1] = 1; breakpoints.push_back(values[i] - 1); } else { for (int j = values[i] - 1; j <= partialSums[i]; ) { int breakPos1 = getNextBreakpointPos(j + 1); int breakPos2 = getNextBreakpointPos(j + values[i] + 1); int break1 = breakpoints[breakPos1]; int break2 = breakpoints[breakPos2]; int dist1 = break1 - j; int dist2 = break2 - j - values[i]; int minDist = min(dist1, dist2); howManyToAdd.push(make_pair(j, (1 + howMany[breakpoints[breakPos1 - 1]] + howMany[breakpoints[breakPos2 - 1]]) % p)); if (j != breakpoints[getNextBreakpointPos(j)]) { breakpoints.push_back(j); } j += minDist; } while (!howManyToAdd.empty()) { howMany[howManyToAdd.top().first] = howManyToAdd.top().second; howManyToAdd.pop(); } } sort(breakpoints.begin(), breakpoints.end()); /*for (int j = 0; j <= partialSums[n - 1]; ++j) { cout << "(" << i << "," << j << "): " << howMany[j] << " "; } cout << endl;*/ } cout << howMany[0] << endl; delete [] partialSums; delete [] howMany; delete [] values; 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 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 | #include <iostream> #include <algorithm> #include <vector> #include <stack> using namespace std; vector<int> breakpoints; unsigned currentBreakpoints; int BST(int start, int end, int val) { if (start == end) { return start; } int mid = (start + end) / 2; if (breakpoints[mid] < val) { return BST(mid + 1, end, val); } else { return BST(start, mid, val); } } int getNextBreakpointPos(int val) { return BST(0, currentBreakpoints - 1, val); } int main() { ios_base::sync_with_stdio(0); int n, a; const long long p = 1000000007; long long *howMany; int *partialSums; int *values; cin >> n; partialSums = new int[n]; values = new int[n]; for (int i = 0; i < n; ++i) { cin >> a; values[i] = a; } sort(values, values + n); partialSums[0] = 0; for (int i = 0; i < n; ++i) { partialSums[i] = partialSums[i - 1] + values[i - 1]; } howMany = new long long[partialSums[n - 1] + 1]; for (int i = 0; i < partialSums[n - 1] + 1; ++i) { howMany[i] = 0; } stack<pair<int, long long>> howManyToAdd; breakpoints.push_back(0); breakpoints.push_back(partialSums[n - 1] + 1); for (int i = n - 1; i >= 0; --i) { // cout << "processing " << i << endl; currentBreakpoints = breakpoints.size(); if (i == n - 1) { howMany[values[i] - 1] = 1; breakpoints.push_back(values[i] - 1); } else { for (int j = values[i] - 1; j <= partialSums[i]; ) { int breakPos1 = getNextBreakpointPos(j + 1); int breakPos2 = getNextBreakpointPos(j + values[i] + 1); int break1 = breakpoints[breakPos1]; int break2 = breakpoints[breakPos2]; int dist1 = break1 - j; int dist2 = break2 - j - values[i]; int minDist = min(dist1, dist2); howManyToAdd.push(make_pair(j, (1 + howMany[breakpoints[breakPos1 - 1]] + howMany[breakpoints[breakPos2 - 1]]) % p)); if (j != breakpoints[getNextBreakpointPos(j)]) { breakpoints.push_back(j); } j += minDist; } while (!howManyToAdd.empty()) { howMany[howManyToAdd.top().first] = howManyToAdd.top().second; howManyToAdd.pop(); } } sort(breakpoints.begin(), breakpoints.end()); /*for (int j = 0; j <= partialSums[n - 1]; ++j) { cout << "(" << i << "," << j << "): " << howMany[j] << " "; } cout << endl;*/ } cout << howMany[0] << endl; delete [] partialSums; delete [] howMany; delete [] values; return 0; } |