kkio。|

_kkio

园龄:1年7个月粉丝:6关注:1

关于一类 1D1D dp 问题的优化技巧

模型:

dpi=minik+1jidpj1+max(aj,aj+1,,ai)

这类问题有简单的 nlogn 做法,但是我们使用线性做法。一个用烂的做法是用均摊的数据结构去维护上面的转移区间,但是这里有一个不一样的线性做法。

对于 i 的转移,考虑找到前面的每一个后缀最值,可以得到若干有用的转移点。若不考虑左端点 ik+1 的限制,这个转移可以被递推去做。具体地,我们维护一个 fri 表示 i 上一个极值点,则可以维护这么转移的 gi=min(ffri+ai,gfri)

现在我们需要解除 ik+1 的限制,考虑将原序列分成长度为 k 的段,每段可以从前面的段转移过来。维护段内前缀最大,后缀最大,可以使用双指针可以维护每个位置的贡献,这里根据不同情况,可以维护单调队列或改变枚举顺序使它的复杂度线性。以此,我们可以用它来解决段外的转移。

对于段内的转移,我们发现,我们统一了 ik+1 的限制,此时,段内的转移便可以通过维护以上的的 gi,线性的从前往后递推。总体上我们将此 dp 优化至线性复杂度。

#include <bits/stdc++.h>
using namespace std;
namespace FastIO {
	struct IO {
	    char ibuf[(1 << 20) + 1], *iS, *iT, obuf[(1 << 20) + 1], *oS;
	    IO() : iS(ibuf), iT(ibuf), oS(obuf) {} ~IO() { fwrite(obuf, 1, oS - obuf, stdout); }
		#if ONLINE_JUDGE
		#define gh() (iS == iT ? iT = (iS = ibuf) + fread(ibuf, 1, (1 << 20) + 1, stdin), (iS == iT ? EOF : *iS++) : *iS++)
		#else
		#define gh() getchar()
		#endif
		inline bool eof (const char &ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == 't' || ch == EOF; }
	    inline long long read() {
	        char ch = gh();
	        long long x = 0;
	        bool t = 0;
	        while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
	        while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gh();
	        return t ? ~(x - 1) : x;
	    }
	    inline void read (char *s) {
	    	char ch = gh(); int l = 0;
	    	while (eof(ch)) ch = gh();
	    	while (!eof(ch)) s[l++] = ch, ch = gh();
	    }
	    inline void read (double &x) {
	    	char ch = gh(); bool t = 0;
	    	while (ch < '0' || ch > '9') t |= ch == '-', ch = gh();
	    	while (ch >= '0' && ch <= '9') x = x * 10 + (ch ^ 48), ch = gh();
	    	if (ch != '.') return t && (x = -x), void(); ch = gh();
	    	for (double cf = 0.1; '0' <= ch && ch <= '9'; ch = gh(), cf *= 0.1) x += cf * (ch ^ 48);
	    	t && (x = -x);
	    }
	    inline void pc (char ch) {
	    	#ifdef ONLINE_JUDGE
	    	if (oS == obuf + (1 << 20) + 1) fwrite(obuf, 1, oS - obuf, stdout), oS = obuf; 
	    	*oS++ = ch;
	    	#else
	    	putchar(ch);
	    	#endif
		}
		template<typename _Tp>
	    inline void write (_Tp x) {
	    	static char stk[64], *tp = stk;
	    	if (x < 0) x = ~(x - 1), pc('-');
			do *tp++ = x % 10, x /= 10;
			while (x);
			while (tp != stk) pc((*--tp) | 48);
	    }
	    inline void write (char *s) {
	    	int n = strlen(s);
	    	for (int i = 0; i < n; i++) pc(s[i]);
	    }
	} io;
	inline long long read () { return io.read(); }
	template<typename Tp>
	inline void read (Tp &x) { io.read(x); }
	template<typename _Tp>
	inline void write (_Tp x) { io.write(x); }
}
using namespace FastIO;
#pragma GCC optmize(2)
const int maxn=1e7+10,mod=1e9+7;
typedef long long ll;
int n,k;
int a[maxn],L[maxn],R[maxn],s[maxn];
ll f[maxn],tf[maxn];
int suf[maxn],pre[maxn],top,stk[maxn],fr[maxn];
int solve(int n,int k,int *s)
{
	for(int i=1;i<=n;i++)a[i]=s[i-1];
//	ios::sync_with_stdio(0),cin.tie(0);
//	freopen("beetle22.in","r",stdin);
//	freopen("1.out","w",stdout);
	for(int i=1;i<=n;i++)tf[i]=-1;
	fr[0]=-1;
	for(int i=1;i<=n;i++)
	{
		while(top&&a[stk[top]]<=a[i])top--;
		if(!top)fr[i]=0;
		else fr[i]=stk[top];
		stk[++top]=i;
	}
	int LEN=(n-1)/k+1;
	for(int i=1;i<=LEN;i++)L[i]=(i-1)*k+1,R[i]=i*k;
	R[LEN]=n;
	for(int i=L[1];i<=R[1];i++)pre[i]=max(pre[i-1],a[i]),f[i]=pre[i];
	for(int i=R[1];i>=L[1];i--)suf[i]=max(suf[i+1],a[i]);
	for(int t=2;t<=LEN;t++)
	{
		pre[L[t]]=a[L[t]];
		for(int i=L[t]+1;i<=R[t];i++)pre[i]=max(pre[i-1],a[i]);
		suf[R[t]]=a[R[t]];
		for(int i=R[t]-1;i>=L[t];i--)suf[i]=max(suf[i+1],a[i]);
		int ptr1=L[t-1];
		ll mn=1e18;
		for(int i=R[t];i>=L[t];i--)
		{
			while(ptr1<=R[t-1]&&suf[ptr1]>pre[i]){if(ptr1>=i-k+1)mn=min(mn,f[ptr1-1]+suf[ptr1]);ptr1++;}
			if(i-k+1<ptr1)mn=min(mn,f[i-k]+suf[i-k+1]);
			f[i]=min(mn,f[max(ptr1-1,i-k)]+pre[i]);
		}
		for(int i=L[t];i<=R[t];i++)
		{
			if(fr[i]>=L[t])tf[i]=min(tf[fr[i]],f[fr[i]]+a[i]);
			else tf[i]=1e18;
			f[i]=min(f[i],tf[i]);
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)ans=(1ll*ans*23%mod+(f[i]%mod))%mod; 
	return ans;
}

本文作者:_kkio

本文链接:https://www.cnblogs.com/hikkio/p/17685614.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _kkio  阅读(64)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起