P2687 [USACO4.3]逢低吸纳Buy Low, Buy Lower

R e s u l t Result Result

...


H y p e r l i n k Hyperlink Hyperlink

https://www.luogu.com.cn/problem/P2687


D e s c r i p t i o n Description Description

给定一个长度为 n n n的序列,求不相交的最长下降序列长度及方案数

数据范围:
n ≤ 5 × 1 0 3 n\leq 5\times 10^3 n5×103


S o l u t i o n Solution Solution

d p dp dp
f i f_i fi表示以 a i a_i ai结尾的 L I S LIS LIS长度, g i g_i gi表示其方案数
a i < a j a_i<a_j ai<aj,有 f i = m a x { f j + 1 } f_i=max\{f_j+1\} fi=max{fj+1}
特别地,当 f j + 1 = f i f_j+1=f_i fj+1=fi时,有 g i = ∑ g j g_i=\sum g_j gi=gj

写完这个代码愉快的交上去,发现只有 50 p t s 50pts 50pts
...
原来是莫得考虑 a i = a j a_i=a_j ai=aj即相交的情况
我们只需要把它们的 g g g清空即可

方案数可能很大,要用高精度
时间复杂度: O ( n 2 l e n ) O(n^2len) O(n2len) l e n len len为高精度数组大小


C o d e Code Code
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
int n,f[5010],a[5010],res;
inline LL read()
{
	char c;LL d=1,f=0;
	while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
struct int233
{
	int t[41];
	int233(){memset(t,0,sizeof(t));}
}g[5010],sum;
inline int233 Add(int233 A,int233 B)
{
	int g=0;
	for(register int j=1;j<=40;j++)
	{
		g=A.t[j]+B.t[j]+g;
		A.t[j]=g%10000;
		g/=10000;
	}
	return A;
}
inline void print(int233 x)
{
	int j=40;
	while(!x.t[j]&&j>1) j--;printf("%d",x.t[j]);
	for(register int i=j-1;i;i--) printf("%04d",x.t[i]);
	return;
}
int main()
{
	n=read();
	for(register int i=1;i<=n;i++)
	{
		a[i]=read();g[i].t[1]=1;f[i]=1;
		for(register int j=1;j<i;j++) 
		{
			if(a[i]>=a[j]) continue;
			if(f[j]+1==f[i]) g[i]=Add(g[i],g[j]);
			if(f[j]+1>f[i])
			{
				memcpy(g[i].t,g[j].t,sizeof(g[j].t));
				f[i]=f[j]+1;
			}
		}
		for(register int j=1;j<i;j++) if(f[i]==f[j]&&a[i]==a[j]) memset(g[j].t,0,sizeof(g[j].t));//特判
		res=max(res,f[i]);//取最大值
	}
	for(register int i=1;i<=n;i++) if(f[i]==res) sum=Add(sum,g[i]);//统计
	printf("%d ",res);print(sum);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值