ACM天才

Author Avatar
Axell 1月 13, 2019
  • 在其它设备中阅读本文章

题目描述

20181211161641_67802.jpg

输入

每个测试点包含多组数据,第一行一个整数T给出数据组数。
对于每组数据,第一行三个整数n, m, k,第二行n个整数P1~Pn。

输出

对于每组数据,输出一个整数表示答案。

样例输入

2
5 1 49
8 2 1 7 9
5 1 64
8 2 1 7 9

样例输出

2
1

提示

思路

首先考虑SPD的计算方式,因为是随机抽取,因此即使是最坏的情况也能通过
那么最坏的情况是什么? 即最大-最小,次大-次小,… 此时SPD在序列不变时,取最大值
所以只需要每次计算出SPD符合条件的最大截取范围即可

首先,每次枚举终点肯定会超时
可以采用倍增的方式,用logn的时间得到最大的划分区间,同时用快速排序以n log n 的复杂度判断,同时有的区间相互包含,因此可以少排一段序,最终归并即可

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n,m,p[500005],t[500005],la[500005],tmp[500005],last,ans;
ll k;
void ms(int l,int r,int mid){
    int i=l,j=mid+1,k=l;
    while (i<=mid && j<=r){
        if (t[i]<=t[j]){
            tmp[k]=t[i];
            k++;
            i++;
        }else{
            tmp[k]=t[j];
            k++;
            j++;
        }
    }
    while (i<=mid){
        tmp[k]=t[i];
        k++;
        i++;
    }
    while (j<=r){
        tmp[k]=t[j];
        k++;
        j++;
    }
    for (int i=l;i<=r;++i){
        t[i]=tmp[i];
    }
}

void sor(int st,int ed){
    for (int i=1;i<=last;++i) t[i]=la[i];
    sort(t+last+1,t+ed+1);
    ms(st,ed,last);
}

ll ch(int st,int ed){
    ll ret=0;
    for (int i=st;i<=ed;++i) t[i-st+1]=p[i];
    ed=ed-st+1;st=1;
    sor(1,ed);
    int mid=(st+ed)>>1;
    for (int i=1;i<=min(mid,m);++i) ret+=(ll)(t[i]-t[ed-i+1])*(t[i]-t[ed-i+1]);
    if (ret<=k && ed<=n){
        for (int i=1;i<=ed;++i) la[i]=t[i];
        last=ed;
    }
    return ret;
}

void solve(){
    scanf("%d %d %lld",&n,&m,&k);
    for (int i=1;i<=n;++i) scanf("%d",&p[i]);
    int l=1;
    ans=0;
    while (l<=n){
        int len=1,r=l;
        last=0;
        while (len){
            if (r+len<=n && ch(l,r+len)<=k) {
                r+=len;
                len<<=1;
            }else{
                len>>=1;
            }
        }
        ans++;
        l=r+1;
    }
    printf("%d\n",ans);
}

int main(){
    // freopen("geniusacm.in", "r", stdin);
    // freopen("geniusacm.out", "w", stdout);
    int t;
    cin>>t;
    while (t--) solve();
    return 0;
}

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 3.0 未本地化版本许可协议进行许可。

本文链接:https://hs-blog.axell.top/archives/65/