CF500F New Year Shopping [线段树分治,背包]

Posted isaunoya

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)] = ‘
‘; }
	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] << ‘
‘;
	return 0;
}

以上是关于CF500F New Year Shopping [线段树分治,背包]的主要内容,如果未能解决你的问题,请参考以下文章

[题解] [CF500F] New Year Shopping

CF 750C New Year and Rating(思维题)

cf723a The New Year: Meeting Friends

CF140C New Year Snowmen

CF620E. New Year Tree

CF 500 C New Year Book Reading