loj # 6039 "Ya Li Training 2017 Day5" jewelry group backpack decision monotonic optimization

LINK: Jewelry

I wrote this question on an oj last year, and at the time, the unconsciousness of the ignorance of ignorance wa finally discovered that this thing turned out to be monotonous.

It can be found that it is a 01 backpack, but it cannot be calmly analyzed. The complexity of the 01 backpack has a lower bound. If it cannot be passed, there must be some special conditions.

Sure enough, the cost of the item is <= 300. A greedy person can obviously choose the largest item with the same cost, and we will press the items with the same cost together.

It can be found that this is similar to dp f [i] of the group backpack, which means the maximum value of i capacity f [i] = max (f [ij * c] + w [c] [j]);

However, the difference of the w array gradually decreases after the difference.

It can be found that monotonic queues can be used for optimization, but we can only maintain half of the monotonic queues because the value of the points in the queue is different each time and is not monotonous.

Therefore, it is impossible to quickly find a decision.

But we can consider the monotonicity of the decision. For i, there is decision ik p or iw p (w> k). If the former is better than the latter, then for a larger i, just ik p is still better than iw p because The w array is monotonically decreasing after difference, so obviously.

So for a point w, the optimal decision is k, then for those points larger than w, the decision is monotonically increasing.

For decision-making monotonic optimization dp can use the divide and conquer method or the dichotomy method of storing triad monotonous queue.

It is recommended to use the divide and conquer method to be simple, rude, and easy to write, with a small constant.

A small pit: when dividing and conquering, it is necessary to update> = because all subsequent decisions may not update the current mid and the point that is equal to mid may update the following points, so we have to keep such a point. Contribute to the back.

It can be found that it has no effect on the front.

const int MAXN=1000010;
int n,m,maxx,now;
vector<ll>v[310];
ll f[MAXN],g[MAXN],s[MAXN],sum[MAXN];
inline ll cmp(ll x,ll y){return x>y;}
inline void solve(int l,int r,int L,int R)//L~R为决策转移空间
{
	int mid=(l+r)>>1;
	int p=mid;g[mid]=s[mid];
	for(int i=L;i<=R&&i<mid;++i)
	{
		ll ww=s[i]+sum[mid-i];
		if(ww>g[mid])g[mid]=ww,p=i;
	}
	if(l<mid)solve(l,mid-1,L,p);
	if(r>mid)solve(mid+1,r,p,R);
}
int main()
{
	freopen("1.in","r",stdin);
	n=read();m=read();
	rep(1,n,i)
	{
		int x=read(),y=read();
		v[x].push_back(y);
		maxx=max(maxx,x);
	}
	rep(1,maxx,i)
	{
		if(!v[i].size())continue;now=i;
		sort(v[i].begin(),v[i].end(),cmp);
		int len=m/i,sz=v[i].size();
		rep(1,len,j)sum[j]=sum[j-1]+(j>sz?0:v[i][j-1]);
		for(int j=0;j<i;++j)
		{
			int top=0;
			for(int k=j;k<=m;k+=i)s[++top]=f[k];
			solve(1,top,1,top);
			for(int k=j,w=1;k<=m;k+=i,++w)f[k]=g[w];
		}
	}
	for(int i=1;i<=m;++i)printf("%lld ",f[i]);
	return 0;
}

Guess you like

Origin www.cnblogs.com/chdy/p/12675181.html