bzoj 1318: [Spoj744] Longest Permutation 智商题

时间:2021-09-15 08:22:40

1318: [Spoj744] Longest Permutation

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 361  Solved: 215
[Submit][Status][Discuss]

Description

给你一个序列A含有n个正整数(1<=Ai<=n)。A的子集形式类如Au, Au+1 ... , Av (1<=u<=v<=n),即必须是连续的。我们感兴趣的是一种子集,它含有元素包括1,2,…k。(k是子集的大小)。
你的任务是找到这种类型的最长的子集。

Input

第一行,一个数n,表示序列A的长度
第二行,n个数,第I个数表示元素Ai

Output

一个数,表示可选子集的长度

Sample Input

5
4 1 2 3 2

Sample Output

4

HINT

你可以选得子集从A1开始到A4,这个子集长度为4,包含了1,2,3,4)
1<=n<=100010

  题解传送门:http://www.shuizilong.com/house/archives/spoj-744-longest-permutation/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 101000
typedef long long qword;
int a[MAXN];
int prv[MAXN];
int pid[MAXN];
int vis[MAXN];
int l[MAXN];
qword s[MAXN];
int bstans=;
void solve(int n)
{
memset(pid,,sizeof(pid));
for (int i=;i<=n;i++)
{
if (a[i]>n)
{
prv[i]=;
a[i]=n+;
}
else
{
prv[i]=pid[a[i]];
pid[a[i]]=i;
}
}
for (int i=;i<=n;i++)
s[i]=s[i-]+a[i];
for (int i=;i<=n;i++)
{
if (a[i]==)
{
int mx=;
for (int j=i+;j<=n && a[j]!=;j++)
l[j]=min(l[j-],prv[j]);
int prvmax=;
for (int j=i;j>= && (j==i || a[j]!=);j--)
{
mx=max(mx,a[j]);
prvmax=max(prvmax,prv[j]);
if (j+mx-<i || j+mx->n)continue;
if (max(prvmax,l[j+mx-])>=j)continue;
if (s[j+mx-]-s[j-]==(qword)(mx+)*mx/)
{
bstans=max(bstans,mx);
}
}
}
}
} int main()
{
freopen("input.txt","r",stdin);
int n;
scanf("%d",&n);
int l,r;
for (int i=;i<=n;i++)
scanf("%d",a+i);
solve(n);
for (int i=;i<=n/;i++)
swap(a[i],a[n-i+]);
solve(n);
printf("%d\n",bstans);
}