1318: [Spoj744] Longest Permutation
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
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=0; void solve(int n) { memset(pid,0,sizeof(pid)); for (int i=1;i<=n;i++) { if (a[i]>n) { prv[i]=0; a[i]=n+1; } else { prv[i]=pid[a[i]]; pid[a[i]]=i; } } for (int i=1;i<=n;i++) s[i]=s[i-1]+a[i]; for (int i=1;i<=n;i++) { if (a[i]==1) { int mx=0; for (int j=i+1;j<=n && a[j]!=1;j++) l[j]=min(l[j-1],prv[j]); int prvmax=0; for (int j=i;j>=1 && (j==i || a[j]!=1);j--) { mx=max(mx,a[j]); prvmax=max(prvmax,prv[j]); if (j+mx-1<i || j+mx-1>n)continue; if (max(prvmax,l[j+mx-1])>=j)continue; if (s[j+mx-1]-s[j-1]==(qword)(mx+1)*mx/2) { bstans=max(bstans,mx); } } } } } int main() { freopen("input.txt","r",stdin); int n; scanf("%d",&n); int l,r; for (int i=1;i<=n;i++) scanf("%d",a+i); solve(n); for (int i=1;i<=n/2;i++) swap(a[i],a[n-i+1]); solve(n); printf("%d\n",bstans); }