CF1131G Most Dangerous Shark题解

假如想象 提交于 2020-10-03 17:25:33

题意:给定m个多米诺骨牌,两两间距离为1,每个骨牌有一个高度h和花费p,推倒一个骨牌需要对应的代价p,可以选择向左或向右推,在选定方向上的h-1个(不包括自身)会被推倒,注意被推倒的骨牌会发生连锁反应,继续推。问:让所有的骨牌倒下,所需要的最小代价。
题解:输入是真的恶心,占据此题30%难度啊这
然后我们考虑如何DP
直接上单调栈
f[i]=min(f[left[i]-1]+co[i],mn[q[0]]);
left[i]表示i向左推能推到的最远点
q是单调栈,q[0]是长度
co是那个代价
q里面所有数满足h[q[pos]]]+q[pos]>i
其实就是向右推的
mn[q[0]]=min(f[i-1]+co[i],mn[q[0]-1]),就是i向右推
记得开long long,空间很大










#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
using namespace std;
ll i,j,k,m,n,o,p,l,s,t,times;
ll left[10000005],q[10000005],h[10000005],co[10000005],mn[10000005],f[10000005];
vector<ll> reh[300005],reco[300005];
void read(ll &x)
{
   
   
	char ch=getchar();x=0;
	while (ch<'0'||ch>'9') ch=getchar();
	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-48,ch=getchar();
}
int main()
{
   
   
	freopen("shark.in","r",stdin);
	freopen("shark.out","w",stdout);
	read(n),read(m);
	for (i=1;i<=n;i++)
	{
   
   
		read(o);
		for (j=1;j<=o;j++) read(p),reh[i].push_back(p);
		for (j=1;j<=o;j++) read(p),reco[i].push_back(p); 
	}
	read(times);
	for (i=1;i<=times;i++)
	{
   
   
		read(o),read(p);
		for (j=0;j<=reh[o].size()-1;j++) h[++h[0]]=reh[o][j],co[++co[0]]=reco[o][j]*p;
	}
	for (i=m;i>=1;i--)
	{
   
   
		while (q[0]&&q[q[0]]-h[q[q[0]]]>=i) left[q[q[0]]]=i+1,q[0]--;
		q[++q[0]]=i;
	}
	memset(q,0,sizeof(q));
	for (i=m;i>=1;i--) 
		if (!left[i]) left[i]=1;
	mn[0]=1e18;
	for (i=1;i<=m;i++)
	{
   
   
		while (q[0]&&q[q[0]]+h[q[q[0]]]<=i) q[0]--;
		f[i]=min(f[left[i]-1]+co[i],mn[q[0]]);
		q[++q[0]]=i;
		mn[q[0]]=min(f[i-1]+co[i],mn[q[0]-1]);
	}
	printf("%lld\n",f[m]);
	return 0;
} 












标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!