Genius ACM

Posted zzctommy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Genius ACM相关的知识,希望对你有一定的参考价值。

这题大概就是说给定一个长为n的序列p,将p分为若干段,使得每段取出m对数,令sum=(sum) 每对数差的平方,在是sum尽量大的条件下,使sum不大于常数k。共T组数据。
对于 100%的数据,(Tle 12),(1le n,mle 5cdot 10^5),(0le kle 10^{18}),(0le Pile 2^{20}) 。时限1s

样例输入

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

样例输出

2
1

这题据说原题时限3s,结果xj搞成1s,然后卡掉了一种算法(好像是std,包括老师说的正解);

思路1(就是被卡掉的):对于每一个左端点,二分右端点(或者倍增上去),暴力sort一下区间,找到最大的满足条件的位置,时间复杂度 (O(n log ^2n))

#include<bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
typedef long long ll;
const int N=500005;
int T,n,m,ans;
ll p[N],k,tmp[N];
inline bool pd(int l,int r)
{
    ll sum=0;
    for(register int i=l;i<=r;++i)
        tmp[i]=p[i];
    sort(tmp+l,tmp+r+1);
    int mx=min(m,(r-l+1)>>1);
    for(register int i=1;i<=mx;++i)
        sum+=(tmp[l+i-1]-tmp[r-i+1])*(tmp[l+i-1]-tmp[r-i+1]);
    return sum<=k;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        ans=0;
        scanf("%d%d%lld",&n,&m,&k);
        for(register int i=1;i<=n;++i)
            scanf("%lld",&p[i]);
        int l=1,r,q;
        while(l<=n)
        {
            r=l;q=1;
            while(q)
            {
                if(r+q<=n&&pd(l,r+q))r+=q,q<<=2;
                else q>>=1;
            }
            l=r+1;
            ++ans;
        }
        printf("%d
",ans);
    }
    return 0;
}

上面那份80pts,卡个常就90了
思路2:每次暴力排序浪费时间,考虑类似归并排序合并2个有序序列。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500005;
int T,n,m,ans;
ll p[N],k,a[N],b[N];
inline void msort(int l,int r,int mid) {
    int x=l,y=l,z=mid+1;
    while(x<=mid&&z<=r) {
        if(a[x]<a[z])b[y++]=a[x++];
        else b[y++]=a[z++];
    }
    while(x<=mid)b[y++]=a[x++];
    while(z<=r)b[y++]=a[z++];
}
inline bool pd(int l,int r,int mid) {
    for(register int i=mid+1;i<=r;++i)a[i]=p[i];
    sort(a+mid+1,a+r+1);
    msort(l,r,mid);
    ll sum=0;
    int num=1,lt=l,rt=r;
    while(lt<rt&&num<=m) {
        ++num;
        ll tmp=b[lt++]-b[rt--];
        sum+=tmp*tmp;
    }
    return sum<=k;
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%lld",&n,&m,&k);
        for(register int i=1; i<=n; ++i)
            scanf("%lld",&p[i]);
        int l=1,r=1,q=1;ans=0;
        a[1]=p[1];
        while(l<=n) {
            while(q) {
                if(r+q<=n&&pd(l,r+q,r)) {
                    r+=q,q<<=1;
                    for(int i=l; i<=r; ++i)
                        a[i]=b[i];
                }
                else q>>=1;
            }
            l=r+1,r=l,++ans,q=1;
        }
        printf("%d
",ans);
    }
    return 0;
}

以上是关于Genius ACM的主要内容,如果未能解决你的问题,请参考以下文章

CH109 Genius ACM 题解报告

CH0601 Genius ACM

hihocoder#1384/北京网络赛2016 Genius ACM 归并排序+倍增

XJ7191 Genius ACM

Google在与Genius的法律斗争中又取得胜利

genius-storage使用文档,一个浏览器缓存工具