BZOJ 3163: [Heoi2013]Eden的新背包问题

cdq+多重背包单调队列优化

那个前缀后缀合并的是真的不靠谱(这明显T的啊)

#include<cstdio>
#include<algorithm>
#include<vector>
#define pr pair<int,int>
#define mp make_pair
#define fr first
#define sc second
using namespace std;
int n,qe,m=1000,ans[300005],F[4005][1005],w[1005],v[1005],c[1005];
vector<pr> vec[1005];
struct node{
	int fr,sc;
}q[1005];
void update(int t,int i){
	for (int d=0; d<v[i]; d++){
		int head=1,tail=0;
		for (int j=0; v[i]*j+d<=m; j++){
			int now=v[i]*j+d;
			while (head<=tail && q[tail].sc<=F[t][now]-j*w[i]) tail--;
			q[++tail]=(node){j,F[t][now]-j*w[i]};
			while (head<=tail && q[head].fr<j-c[i]) head++;
			F[t][now]=0;
			if (head<=tail) F[t][now]=q[head].sc+j*w[i];
		}
	}
}
void solve(int t,int l,int r){
	if (l==r){
		for (int i=1; i<=m; i++) F[t][i]=max(F[t][i],F[t][i-1]);
		for (int i=0; i<(int)vec[l].size(); i++) ans[vec[l][i].fr]=F[t][vec[l][i].sc];
		return;
	}
	int mid=(l+r)>>1;
	for (int i=0; i<=m; i++) F[t<<1][i]=F[t<<1|1][i]=F[t][i];
	for (int i=mid+1; i<=r; i++) update(t<<1,i);
	solve(t<<1,l,mid);
	for (int i=l; i<=mid; i++) update(t<<1|1,i);
	solve(t<<1|1,mid+1,r);
}
int main(){
	scanf("%d",&n);
	for (int i=1; i<=n; i++) scanf("%d%d%d",&v[i],&w[i],&c[i]);
	scanf("%d",&qe);
	for (int i=1; i<=qe; i++){
		int x,y;
		scanf("%d%d",&x,&y);
		x++;
		vec[x].push_back(mp(i,y));
	}
	solve(1,1,n);
	for (int i=1; i<=qe; i++) printf("%d
",ans[i]);
	return 0;
}

  

原文地址:https://www.cnblogs.com/silenty/p/9917818.html