听说学术区人多。关于单调队列优化DP。
  • 板块学术版
  • 楼主ShanQing
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/8/18 23:10
  • 上次更新2023/11/3 02:47:01
查看原帖
听说学术区人多。关于单调队列优化DP。
368204
ShanQing楼主2023/8/18 23:10

这是P3084的AC代码。有些地方对着题解打的,轻点喷谢谢。

//writer:Oier_szc

#include <bits/stdc++.h>
#define TS puts("I AK IOI");
//#define int long long
using namespace std;
const int N=1e5+5,M=2e5+5;
int n,m,ans=-1;
struct node
{
	int l,r;
}a[N];
int maxl[M],minl[M];
int f[M];
int q[M],hh=0,tt=0;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n+1;++i) minl[i]=i-1;
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		minl[a[i].r]=min(minl[a[i].r],a[i].l-1);
		maxl[a[i].r+1]=max(maxl[a[i].r+1],a[i].l);
	}
	for(int i=n;i>=1;--i)
	{
		minl[i]=min(minl[i],minl[i+1]);
	}
	for(int i=2;i<=n+1;++i)
	{
		maxl[i]=max(maxl[i],maxl[i-1]);
	}
	int now=1;
	for(int i=1;i<=n+1;++i)
	{

		while(now<=n&&now<=minl[i])
		{
			if(f[now]==-1) 
			{
				++now;
				continue;
			}
			while(hh<=tt&&f[now]>f[q[tt]]) --tt;
			q[++tt]=now;
			++now;
		}
		while(hh<=tt&&q[hh]<maxl[i]) ++hh;
		//cout<<i<<" "<<hh<<" "<<tt<<" "<<now<<endl;
		if(hh<=tt) 
		{
			f[i]=f[q[hh]]+(i!=n+1?1:0);
		}
		else f[i]=-1;
	}
	printf("%d\n",f[n+1]);
	return 0;
}

考虑调换加入元素和弹出元素的执行顺序,变成这样。

//writer:Oier_szc

#include <bits/stdc++.h>
#define TS puts("I AK IOI");
//#define int long long
using namespace std;
const int N=1e5+5,M=2e5+5;
int n,m,ans=-1;
struct node
{
	int l,r;
}a[N];
int maxl[M],minl[M];
int f[M];
int q[M],hh=0,tt=0;
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n+1;++i) minl[i]=i-1;
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		minl[a[i].r]=min(minl[a[i].r],a[i].l-1);
		maxl[a[i].r+1]=max(maxl[a[i].r+1],a[i].l);
	}
	for(int i=n;i>=1;--i)
	{
		minl[i]=min(minl[i],minl[i+1]);
	}
	for(int i=2;i<=n+1;++i)
	{
		maxl[i]=max(maxl[i],maxl[i-1]);
	}
	int now=1;
	for(int i=1;i<=n+1;++i)
	{
		while(hh<=tt&&q[hh]<maxl[i]) ++hh;
		while(now<=n&&now<=minl[i])
		{
			if(f[now]==-1) 
			{
				++now;
				continue;
			}
			while(hh<=tt&&f[now]>f[q[tt]]) --tt;
			q[++tt]=now;
			++now;
		}
		
		//cout<<i<<" "<<hh<<" "<<tt<<" "<<now<<endl;
		if(hh<=tt) 
		{
			f[i]=f[q[hh]]+(i!=n+1?1:0);
		}
		else f[i]=-1;
	}
	printf("%d\n",f[n+1]);
	return 0;
}

然后样例输出2,答案是1。

已经不止一次遇到过该情况,至今不知道原因。希望dalao解答。如果这个问题很显然的话请大声呵斥SZC的蒻。

2023/8/18 23:10
加载中...