[bzoj3100]排列

题目大意

给定长度为N的序列,权值范围在[1,n]。
求一个长度最大的区间使该区间是一个包含1的排列。
n<=1e6,空间限制16M

做法

一个区间合法的条件?
1、包含1
2、所有元素互不相同
3、若长度为k,区间和为k*(k+1)/2
这样的区间的性质?
最大值等于区间长度。
这样的区间最大值可以在1左边或右边,做两次即可,下面假设最大值在1右边。
枚举每一个1,然后枚举右端点的位置(显然在该1右边)
假如枚举的右端点位置是r,1的位置是i,[i,r]最大值为mx。根据性质,现在枚举的区间就是[r-mx+1,r]。
为了满足条件2,我们需要预处理left表示一个数左边第一个和其相同的位置(这个预处理需要两个数组),那么我们求出[i,r]的left的max,便可以判断[r-mx+1,r]是否合法,同时为了满足条件3,需要用前缀和来计算。
复杂度显然线性。
前缀和数组应该是个long long算两个数组,加上原数组,计算left所用两个数组,总共是5个数组,boom。
原数组和前缀和数组显然可以共用,总共是4个数组,boom。
left不要预处理,即算即用,3个数组,可以。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=1000000+2;
typedef long long ll;
ll a[maxn];
int last[maxn];
int i,n,ans,mx,wz;
void calc(){
    int j,l;
    ans=max(ans,1);
    mx=1;
    l=last[a[i]-a[i-1]];
    last[a[i]-a[i-1]]=i;
    wz=l+1;
    fo(j,i+1,n+1){
        if (j>n||a[j]-a[j-1]==1) break;
        l=last[a[j]-a[j-1]];
        last[a[j]-a[j-1]]=j;
        wz=max(wz,l);
        mx=max(mx,int(a[j]-a[j-1]));
        if (wz<=j-mx+1)
            if (a[j]-a[j-mx]==(ll)mx*(mx+1)/2) ans=max(ans,mx);
    }
    i=j;
}
int main(){
    scanf("%d",&n);
    fo(i,1,n){
        scanf("%d",&a[i]);
        //sum[i]=sum[i-1]+(ll)a[i];
        //left[i]=last[a[i]];
        //last[a[i]]=i;
    }
    fo(i,1,n) a[i]+=a[i-1];
    fo(i,1,n){
        if (a[i]-a[i-1]==1) break;
        last[a[i]-a[i-1]]=i;
    }
    while (i<=n){
        calc();
    }
    fd(i,n,1) a[i]-=a[i-1];
    fo(i,1,n/2) swap(a[i],a[n-i+1]);
    fo(i,1,n) a[i]+=a[i-1];
    fo(i,1,n) last[i]=0;
    fo(i,1,n){
        if (a[i]-a[i-1]==1) break;
        last[a[i]-a[i-1]]=i;
    }
    while (i<=n){
        calc();
    }
    printf("%d\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值