【UER #7】套路

55 篇文章 0 订阅
44 篇文章 0 订阅

题目链接

【UER #7】套路

Description

反攻正在进行中,按照套路,跳蚤国将会很快获得最终的胜利。跳蚤国的情报局也没闲下来,他们正打算派遣一批“菲克蚤”前往跳晚国窃取有关三星 note7 的资料。
Fake Yang 是这批“菲克蚤”的教练,他教会他们各种 Fake 的技术,以便更好混入敌方内部。共 n 只菲克蚤,由 1到 n编号。Fake Yang 给每个菲克蚤都算了特征值 a1,…,an,两个菲克蚤的相似度定义成这两个菲克蚤的特征值的差的绝对值,即第 i 只菲克蚤与第 jj 只菲克蚤的相似度为 ∣ai−aj|
现在这批菲克蚤排成一列在 Fake Yang 面前,Fake Yang 需要在其中选出一些菲克蚤合成一个行动小队。按照套路,他会选取连续一整段的菲克蚤 al,al+1,…,ar。很显然,这个行动小队越大越好,但是按照套路,小队内的跳蚤最好都各不相同,假如有两只跳蚤长得很像的话很可能会引起跳晚们的怀疑。为此 Fake Yang 将小队的相似度定义为小队中的跳蚤两两之间的最小的相似度,用 s(l,r) 表示。
为保证安全,现在他想选取至少 kk 只跳蚤,且使得安全值最大。其中安全值定义如下:
s(l,r)×(r−l)
但是,他并不知道最优解是什么,于是按照套路你需要帮助他求得这个值。
输入格式
按照套路,第一行三个正整数 n,m,k。k 的意义如前所述,n 表示跳蚤的只数。
接下来一行 nn 个整数,按照套路依次表示 n 只跳蚤的特征值 a1,…,an,保证 1≤ai≤m。
输出格式
按照套路,一行一个整数,表示答案。

input

10 10 2
1 4 2 6 1 9 6 8 10 3

output

8

explanation

一种方案是选取区间 [5,6],相似度为 8,答案为8×(6−5)=8。
限制与约定
由于一些原因,本题我们需要按照套路使用捆绑测试。每个子任务有若干个测试点,分为 5 个子任务,你只有通过一个子任务的所有测试点才能按照套路得到这个子任务的分数。
在所有数据中,满足 2≤n≤200000,1≤m≤200000,2≤k≤n
时间限制:2s
空间限制:256MB

Solution

这题也是一道理解题
分类讨论
设它区间的大小为K
设S为区间内的安全值
那么当K小于一个常数M时,枚举这个K,利用DP求出答案
设f[i,j]表示当前区间结尾为i,长度为j,的S值
f[i,j]=min(f[i,j1],f[i1,j1],|a[i]a[ij+1]|)
十分简单
当K大于这个常数M时,S的值小于n/M,所以枚举S的值
这是就很显然了 M=n
先枚举区间的结尾i,然后枚举S的值,设为j
那么需要求出区间的开头l
l要满足什么条件呢?
设r[x]表示在当前枚举的i之前,x这个数出现的最晚位置
那么,可取的数在a[i]-j~a[i]+j之间,才能保证合法
那么l就必须在r[a[i]-j]和r[a[i]+j]右边,就保证了l到i之间没有不合法的数
除此之外,对于结尾i对应的开头l,必须大于曾经已经求出来过的l,为什么呢?自行脑补

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define N 201000
#define M 520
using namespace std;
int n,m,k,a[N],f[N][2],r[N],c[N];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int ans=0,l=0;
    fo(i,1,n) scanf("%d",&a[i]),f[i][1]=214748367;
    fo(j,2,min(M,n))
    {
        fo(i,j,n) f[i][l]=min(abs(a[i]-a[i-j+1]),min(f[i][1-l],f[i-1][1-l])),ans=max(ans,f[i][l]*(j-1)*(j>=k));
        l=1-l;
    }
    r[a[1]]=1;
    fo(i,2,n)
    {
        l=1;
        fo(j,0,min(m,M))
        {
            if(i-l+1>=k) ans=max(ans,(i-l)*j);
            if(a[i]>j) c[j]=max(c[j],r[a[i]-j]);
            c[j]=max(c[j],r[a[i]+j]);l=max(l,c[j]+1);

        }
        r[a[i]]=i;
    }
    printf("%d",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值