CF500F New Year Shopping [线段树分治,背包]
不会奇怪的背包科技,只能用线段树分治了。
// by Isaunoya
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct io {
char buf[1 << 25 | 3], *s;
int f;
io() { f = 0, buf[fread(s = buf, 1, 1 << 25, stdin)] = '\n'; }
io& operator >> (int&x) {
for(x = f = 0; !isdigit(*s); ++s) f |= *s == '-';
while(isdigit(*s)) x = x * 10 + (*s++ ^ 48);
return x = f ? -x : x, *this;
}
};
struct io_out {
char buf[1 << 25 | 3], *s = buf;
~io_out() { fwrite(buf, 1, s - buf, stdout); }
void write(int x) { if(x > 9) write(x / 10); *s++ = x % 10 ^ '0'; }
io_out& operator << (int x) {
if(x < 0) x = -x, *s++ = '-';
write(x); return *this;
}
io_out& operator << (char x) { *s++ = x; return *this; }
} out;
int n, p, q;
const int lg = 40;
const int lim = 2e4 + 42;
const int maxn = 4444;
int st[lg][maxn], f[maxn], top;
int c[maxn], h[maxn];
vector <int> vec[lim << 2];
void upd(int ql, int qr, int l, int r, int p, int x) {
if(ql <= l && r <= qr) {
vec[p].push_back(x);
return;
}
int mid = l + r >> 1;
if(ql <= mid)
upd(ql, qr, l, mid, p << 1, x);
if(qr > mid)
upd(ql, qr, mid + 1, r , p << 1 | 1 , x);
return ;
}
const int maxq = 2e4 + 42;
int a[maxq], b[maxq], ans[maxq];
vector <int> tq[lim];
void takenew() {
++ top;
for(int i = 0 ; i <= 4000 ; i ++) st[top][i] = f[i];
}
void back() {
-- top;
for(int i = 0 ; i <= 4000 ; i ++) f[i] = st[top][i];
}
void solve(int l, int r, int p) {
for(int id : vec[p])
for(int i = 4000; i >= c[id]; i --) f[i] = max(f[i], f[i - c[id]] + h[id]);
takenew();
if(l == r) { for(int x : tq[l]) ans[x] = f[b[x]]; }
else {
int mid = l + r >> 1;
solve(l, mid, p << 1), solve(mid + 1, r, p << 1 | 1);
}
back();
}
signed main() {
#ifdef LOCAL
freopen("testdata.in", "r", stdin);
#endif
io in;
in >> n >> p;
for(int i = 1 ; i <= n ; i ++) {
int t ;
in >> c[i] >> h[i] >> t;
upd(t, t + p - 1, 1 , lim , 1, i);
}
in >> q;
for(int i = 1 ; i <= q ; i ++) {
in >> a[i] >> b[i];
tq[a[i]].push_back(i);
}
solve(1, lim, 1);
for(int i = 1 ; i <= q ; i ++)
out << ans[i] << '\n';
return 0;
}