bzoj 1318: [Spoj744] Longest Permutation 智商题

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=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);
}

 

转载于:https://www.cnblogs.com/mhy12345/p/4569469.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值