文章目录
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
n≤5×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);
}