[UOJ#246][UER#7C]套路(数luan学gao相关)

算法优化竞赛题解析
本文针对一道算法竞赛题目,提出了四种不同的解决方案,包括暴力求解、动态规划、结合抽屉原理以及混合策略优化等方法,并详细阐述了每种算法的时间复杂度及预期得分情况。

题目描述

传送门

题解

算法一
直接上暴力。。。时间复杂度 O(n4) ,期望得分7分。

算法二
s(l,r) 表示l~r这一段两两差的最小值,那么可以递推: s(l,r)=min(|alar|,min(s(l,r1),s(l+1,r)))
求出 s(l,r) 了之后就可以暴力枚举了。时间复杂度 O(n2) ,期望得分20分。
这里的数组可以开成一维的,不过需要用一个特别的技巧:从后向前递推,数组里保留上一次递推的答案,那么
f[j]=min(f[j],f[j-1]),f[j]=min(f[j],Abs(a[j]-a[i]));其中第一次用f[j]来更新f[j]就是用上一次的答案来更新当前的答案。

算法三
由于m比较小,根据抽屉原理,一旦区间长度大于m,那么一定存在两个点相等,那么答案就为0了。所以我们只需要考虑区间长度<=m的部分,时间复杂度 O(nm) 。再结合算法二加点什么滚动数组之类的优化,期望得分40分。

算法四
设区间的长度为x,那么最小值不超过 mx1
设一个常数 S
若x<=S,那么用算法三的方法,可以做到O(nS)
若x>S,那么最小差不会超过 mS1 。设 rx 表示权值为x的数最后出现的位置。每次新加入一个数 z 了之后,枚举差值|zy|,对于所有的 |zy|<=mS1 ,用 ry 来更新答案。然后每一次更新 rx 就可以了。
不过这里有很多需要注意的问题。首先是算区间的长度,区间中的元素个数当然是r-l+1,但是题目中所给的计算公式实际上是r-l。在算法四中,如果用f[i]来表示当前右端点为r时,左端点能到的最远点(不包括f[i]),那么最后计算答案的时候应该是i-f[i]-1,而且差值不应该是枚举的差值,而应该+1。

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define LL long long
#define N 200005

int n,m,k,S;
int a[N],f[N],r[N];
LL ans;

int Abs(int x)
{
    return (x>0)?x:-x;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for (int i=1;i<=n;++i) scanf("%d",&a[i]);
    S=sqrt(m);

    memset(f,127,sizeof(f));
    for (int i=n;i>=1;--i)
        for (int j=i+1;j<=min(n,i+S-1);++j)
        {
            f[j]=min(f[j],f[j-1]);
            f[j]=min(f[j],Abs(a[j]-a[i]));
            if (j-i+1>=k)
                ans=max(ans,(LL)f[j]*(j-i));
        }

    memset(f,0,sizeof(f));
    for (int i=1;i<=n;++i)
    {
        for (int j=0;j<=m/S+1;++j)
        {
            if (j>=1) f[j]=max(f[j],f[j-1]);
            if (a[i]-j>=1) f[j]=max(f[j],r[a[i]-j]);
            if (a[i]+j<=m) f[j]=max(f[j],r[a[i]+j]);
            if (i-f[j]>=max(k,S))
                ans=max(ans,(LL)(i-f[j]-1)*(j+1));
        }
        r[a[i]]=i;
    }
    printf("%lld\n",ans);
}

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值