hihocoder 1384 Genius ACM

来源:互联网 发布:linux中expect 编辑:程序博客网 时间:2024/05/22 12:38

#1384 : Genius ACM

时间限制:3000ms
单点时限:3000ms
内存限制:256MB

描述

Advanced CPU Manufacturer (ACM) is one of the best CPU manufacturer in the world. Every day, they manufacture n CPU chips and sell them all over the world.

As you may know, each batch of CPU chips must pass a quality test by the QC department before they can be sold. The testing procedure is as follows:

1) Randomly pick m pairs of CPU chips from the batch of chips (If there are less than 2m CPU chips in the batch of chips, pick as many pairs as possible.)

2) For each pair, measure the Relative Performance Difference (RPD) between the two CPU chips. Let Di be the RPD of the i-th pair

3) Calculate the Sqared Performance Difference (SPD) of the batch according to the following formula:

SPD=∑Di2

If there are only 1 CPU in a batch, then the SPD of that batch is 0.

4) The batch of chips pass the test if and only if SPD≤k, where k is a preseted constant

Usually they send all the n CPU chips as a single batch to the QC department every day. As one of the best CPU manufacturer in the world, ACM never fail the test. However, with the continuous improvement of CPU performance, they find that they are at risk!

Of course they don't want to take any risks. So they make a decision to divide the n chips into several batches to ensure all of them pass the test. What’s more, each batch should be a continuous subsequence of their productions, otherwise the QC department will notice that they are cheating. Quality tests need time and money, so they want to minimize the number of batches.

Given the absolute performance of the n chips P1 ...Pn mesured by ACM in order of manufacture, your task is to determine the minimum number of batches to ensure that all chips pass the test. The RPD of two CPU chips equals to the difference of their absolute performance.

输入

The first line contains a single integer T, indicating the number of test cases.

In each test case, the first line contains three integers n, m, k. The second line contains n integers, P1 ...Pn.

T≤12
1≤n,m≤5×105
0≤k≤1018
0≤Pi≤220

输出

For each test case, print the answer in a single line.

样例输入
25 1 498 2 1 7 95 1 648 2 1 7 9
样例输出
21
北京网络赛的题目。读题的时候就没太读好。虽然知道贪心,但是贪错了。
题意: 给定一段数组,按照原有的顺序,将其划分成几个区间,保证每个区间里 任意取出M对数其差的平方和小于K ,如果取不出M 对就尽量多取。
思路是固定区间左侧,贪心枚举右侧,枚举右侧的时候可以 先找到 kk 满足 [l,l+2^kk]满足小于k,而[l,l+2^(kk+1)]不满足,然后在这个区间二分查找。然后对于求区间里其最大值的方法是将区间排序,
然后一次将最大值和最小值作为一对,将次小和次大作为一对。依次取M对。此时其差的平方和最大。对于排序的小技巧就不赘述了。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;typedef long long int ll;ll m,n,k;ll a[500050];ll b[500050];int cnt=0;inline bool cmp(int x,int y){    return a[x]<a[y];}bool judge(int l,int r){    int pos=0;    while(l+pos<=r)b[pos]=a[l+pos],pos++;    sort(b,b+pos);    pos--;    int mid=(pos-1)/2;    ll res=0;    for(int i=0; i<=mid&&i<m; i++)    {        res+=(b[i]-b[pos-i])*(b[i]-b[pos-i]);        if(res>k)            return false;    }    return res<=k;}void init(int l,int r){    cnt=0;    for(int i=l; i<=r; i++)b[cnt++]=i;    sort(b,b+cnt,cmp);}bool judge2(int r){    int i,j,kk;    ll res=0;    for(i=0,j=cnt-1,kk=m; kk; i++,j--,kk--)    {        while(i<j&&b[i]>r)i++;        while(i<j&&b[j]>r)j--;        if(i>=j)break;        res+=(a[b[i]]-a[b[j]])*(a[b[i]]-a[b[j]]);        if(res>k)break;    }    return res<=k;}int main(){    int T;    scanf("%d",&T);    while(T--)    {        scanf("%lld%lld%lld",&n,&m,&k);        for(int i=0; i<n; i++)            scanf("%lld",&a[i]);        int ans=0;        int l=0;        while(l<n)        {            int kk=1;            while(kk+l<n&&judge(l,l+kk))                kk*=2;            int first=l+kk/2,last=l+kk-1<n?l+kk-1:n-1;            init(l,last);            int mid;            int pos=l;            while(first<=last)            {                if(judge2(mid=(first+last)/2))                {                    first=mid+1;                    pos=mid;                }                else                    last=mid-1;            }            l=pos+1;            ans++;        }        cout<<ans<<endl;    }    return 0;}



0 0
原创粉丝点击