#include <iostream> #include <vector> #include <algorithm> using namespace std; int n, k, q; struct query { int a; int b; int id; bool operator<(const query& other) const { if (a == other.a) { return b > other.b; } return a < other.a; } }; bool appeared_start[300001]; bool appeared_end[300001]; long as[300001]; long str_ending_at[300001]; long str_upto[300001]; long str_so_far = 0; long ans[300001]; int main() { cin >> n >> k >> q; vector<query> queries; for (int i = 0; i < n; ++i) { cin >> as[i]; } for (int i = 0; i < q; ++i) { int a,b; cin >> a >> b; if (b - a + 1 < k) { ans[i] = 0; } else { appeared_start[a-1] = 1; appeared_end[b-1] = 1; query x{a - 1, b - 1, i}; queries.push_back(x); } } int total_start = 0; int total_end = 0; for (int i = 0; i < n; ++i) { total_start += appeared_start[i]; total_end += appeared_end[i]; } // for (int i = 0; i < n; ++i) { // cerr << as[i] << " "; // } // // cerr << endl; if (total_end < total_start) { // if (false) { // reverse the table and all queries reverse(as, as+n); for(int i = 0; i < queries.size(); ++i) { int olda = queries[i].a; int oldb = queries[i].b; queries[i].a = n - oldb - 1; queries[i].b = n - olda - 1; } } // for (int i = 0; i < n; ++i) { // cerr << as[i] << " "; // } // // cerr << endl; for (int i = 0; i < n; ++i) { str_so_far += as[i]; str_upto[i] = str_so_far; } str_ending_at[k-1] = str_upto[k-1]; for (int i = k; i < n; ++i) { str_ending_at[i] = str_upto[i] - str_upto[i-k]; } sort(queries.begin(), queries.end()); // for (int i = 0; i < queries.size(); ++i) { // cerr << queries[i].id << ": " << queries[i].a << " " << queries[i].b << endl; // } long res_upto[n]; for(int i = 0; i < k-1; ++i) { res_upto[i] = 0; } int lasta = -1; for (int i = 0; i < queries.size(); ++i) { // count only needed values // can be optimized to re-use values after K int a = queries[i].a; int b = queries[i].b; if (queries[i].a != lasta) { res_upto[k-1] = max(0L, str_ending_at[a+k-1]); // cerr << "UPTO " << k-1 << ": " << res_upto[k-1] << endl; for (long j = a+k; j <= b; ++j) { res_upto[j - a] = max(res_upto[j - a - k] + str_ending_at[j], res_upto[j - a - 1]); // cerr << "UPTO " << j-a << ": " << res_upto[j-a] << endl; // cerr << "UPTO_pr " << res_upto[j-a-k] << "; STR_end " << str_ending_at[j] << endl; } lasta = queries[i].a; } ans[queries[i].id] = res_upto[b-a]; } for (int i = 0; i < q; ++i) { cout << ans[i] << endl; } 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 114 115 116 117 118 119 120 121 122 123 124 125 | #include <iostream> #include <vector> #include <algorithm> using namespace std; int n, k, q; struct query { int a; int b; int id; bool operator<(const query& other) const { if (a == other.a) { return b > other.b; } return a < other.a; } }; bool appeared_start[300001]; bool appeared_end[300001]; long as[300001]; long str_ending_at[300001]; long str_upto[300001]; long str_so_far = 0; long ans[300001]; int main() { cin >> n >> k >> q; vector<query> queries; for (int i = 0; i < n; ++i) { cin >> as[i]; } for (int i = 0; i < q; ++i) { int a,b; cin >> a >> b; if (b - a + 1 < k) { ans[i] = 0; } else { appeared_start[a-1] = 1; appeared_end[b-1] = 1; query x{a - 1, b - 1, i}; queries.push_back(x); } } int total_start = 0; int total_end = 0; for (int i = 0; i < n; ++i) { total_start += appeared_start[i]; total_end += appeared_end[i]; } // for (int i = 0; i < n; ++i) { // cerr << as[i] << " "; // } // // cerr << endl; if (total_end < total_start) { // if (false) { // reverse the table and all queries reverse(as, as+n); for(int i = 0; i < queries.size(); ++i) { int olda = queries[i].a; int oldb = queries[i].b; queries[i].a = n - oldb - 1; queries[i].b = n - olda - 1; } } // for (int i = 0; i < n; ++i) { // cerr << as[i] << " "; // } // // cerr << endl; for (int i = 0; i < n; ++i) { str_so_far += as[i]; str_upto[i] = str_so_far; } str_ending_at[k-1] = str_upto[k-1]; for (int i = k; i < n; ++i) { str_ending_at[i] = str_upto[i] - str_upto[i-k]; } sort(queries.begin(), queries.end()); // for (int i = 0; i < queries.size(); ++i) { // cerr << queries[i].id << ": " << queries[i].a << " " << queries[i].b << endl; // } long res_upto[n]; for(int i = 0; i < k-1; ++i) { res_upto[i] = 0; } int lasta = -1; for (int i = 0; i < queries.size(); ++i) { // count only needed values // can be optimized to re-use values after K int a = queries[i].a; int b = queries[i].b; if (queries[i].a != lasta) { res_upto[k-1] = max(0L, str_ending_at[a+k-1]); // cerr << "UPTO " << k-1 << ": " << res_upto[k-1] << endl; for (long j = a+k; j <= b; ++j) { res_upto[j - a] = max(res_upto[j - a - k] + str_ending_at[j], res_upto[j - a - 1]); // cerr << "UPTO " << j-a << ": " << res_upto[j-a] << endl; // cerr << "UPTO_pr " << res_upto[j-a-k] << "; STR_end " << str_ending_at[j] << endl; } lasta = queries[i].a; } ans[queries[i].id] = res_upto[b-a]; } for (int i = 0; i < q; ++i) { cout << ans[i] << endl; } return 0; } |