#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; } |
English