码迷,mamicode.com
首页 > 其他好文 > 详细

Genius ACM

时间:2020-02-21 16:33:25      阅读:94      评论:0      收藏:0      [点我收藏+]

标签:排序   合并   optimize   space   reg   ++   its   有序   for   

这题大概就是说给定一个长为n的序列p,将p分为若干段,使得每段取出m对数,令sum=\(\sum\) 每对数差的平方,在是sum尽量大的条件下,使sum不大于常数k。共T组数据。
对于 100%的数据,\(T\le 12\),\(1\le n,m\le 5\cdot 10^5\),\(0\le k\le 10^{18}\),\(0\le Pi\le 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\n",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\n",ans);
    }
    return 0;
}

Genius ACM

标签:排序   合并   optimize   space   reg   ++   its   有序   for   

原文地址:https://www.cnblogs.com/zzctommy/p/12341650.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!