【题解】【LibreOJ Round #6】花团 LOJ 534 时间线段树分治 背包

Prelude

题目链接:萌萌哒传送门(/≧▽≦)/


Solution

如果完全离线的话,可以直接用时间线段树分治来做,复杂度\(O(qv \log q)\)
现在在线了怎么办呢?
这其实是个假在线,因为每个物品的删除时间已经给你了,所以还是直接用时间线段树分治来做。
其实我是重点想谈一下复杂度的,\(O(n^{2} \log n)\)的复杂度居然都可以出到\(15000\),而且居然还跑的飞快?


Code

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <utility>
#include <vector>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef long double ldouble;
typedef pair<int,int> pii;
typedef vector<pii>::iterator viter;
const int MAXN = 15010;
const int LOGN = 17;
const int INF = 0x3f3f3f3f;
int _w;

inline void bmin( int &a, int b ) {
	a = b < a ? b : a;
}
inline void bmax( int &a, int b ) {
	a = b > a ? b : a;
}

int q, maxv, T, lastans;

struct Knapsack {
	int f[MAXN];
	void init() {
		for( int i = 0; i <= maxv; ++i )
			f[i] = -INF;
		f[0] = 0;
	}
	void insert( int v, int w ) {
		for( int i = maxv-v; i >= 0; --i )
			bmax( f[i+v], f[i]+w );
	}
	const int &operator[]( int i ) const {
		return f[i];
	}
	int &operator[]( int i ) {
		return f[i];
	}
};

vector<pii> item[MAXN<<2];
Knapsack f[LOGN];
int qv[MAXN];

pii ins;
int ql, qr;
void insert( int o, int L, int R ) {
	if( L >= ql && R <= qr ) {
		item[o].push_back(ins);
	} else {
		int M = (L+R)>>1, lc = o<<1, rc = lc|1;
		if( ql <= M ) insert(lc, L, M);
		if( qr > M ) insert(rc, M+1, R);
	}
}
void query( int i, int d ) {
	if( qv[i] != -1 ) {
	    int v = qv[i];
		if( f[d][v] < 0 ) {
			puts("0 0");
			lastans = 0;
		} else {
			printf( "1 %d\n", f[d][v] );
			lastans = T * (f[d][v] ^ 1);
		}
	}
	if( i == q ) return;
	int op;
	_w = scanf( "%d", &op );
	if( op == 1 ) {
		int v, w, e;
		_w = scanf( "%d%d%d", &v, &w, &e );
		v -= lastans, w -= lastans, e -= lastans;
		ins = pii(v, w), ql = i+1, qr = e;
		insert(1, 0, q);
	} else {
		_w = scanf( "%d", qv+i+1 );
		qv[i+1] -= lastans;
	}
}
void solve( int o, int L, int R, int d ) {
	for( viter it = item[o].begin(); it != item[o].end(); ++it )
		f[d].insert(it->first, it->second);
	if( L == R ) {
		query(L, d);
	} else {
		int M = (L+R)>>1, lc = o<<1, rc = lc|1;
		f[d+1] = f[d];
		solve(lc, L, M, d+1);
		f[d+1] = f[d];
		solve(rc, M+1, R, d+1);
	}
}

int main() {
	_w = scanf( "%d%d%d", &q, &maxv, &T );
	f[0].init();
	memset(qv, -1, sizeof qv);
	solve(1, 0, q, 0);
	return 0;
}
posted @ 2017-11-06 09:16  mlystdcall  阅读(388)  评论(0编辑  收藏  举报