zoukankan      html  css  js  c++  java
  • hihoCoder #1384 : Genius ACM [枚举+倍增]

    描述
    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.

    样例输入
    2
    5 1 49
    8 2 1 7 9
    5 1 64
    8 2 1 7 9
    样例输出
    2
    1
    .
    .
    .
    .
    .

    分析

    固定区间左侧,类似倍增的思想枚举右侧,
    设当前的左侧是l,然后[l,l+2r]是合法的,[l,l+2r+1]是不合法的,
    那么在我们此时在[l+2r,l+2r+1]二分
    然后每个区间的合法就是要满足那个小于k,就是就是最大的m个数跟最小的m个数一一对应然后计算得到的结果小于k,因为这样计算最大,而最大值小于k则这个区间合法。
    .
    .
    .
    .
    .

    程序:
    #include<iostream>
    #include<algorithm>
    using namespace std;
    long long a[500005],b[500005],k;
    int n,m,tj;
    
    bool cmp(int x,int y)
    {
        return a[x]<a[y];
    }
    
    bool check(int l,int r)
    {
        int num=1;
        while (l+num-1<=r) 
        {
            b[num]=a[l+num-1];
            num++;
        }
        num--;
        sort(b+1,b+num+1);
        int x=1,y=num,cnt=0;
        long long rp=0;
        while (x<y&&cnt<m)
        {
            rp+=(b[y]-b[x])*(b[y]-b[x]);
            if (rp>k) return 0;
            cnt++;
            x++;
            y--;
        }
        if (rp<=k) return true;else return false;
    }
    
    bool work(int w)
    {
        int x=1,y=tj,c=0;
        long long r=0;
        while (x<y&&c<m)
        {
            c++;
            while (x<y&&b[x]>w) x++;
            while (x<y&&b[y]>w) y--;
            if (x>=y) break;
            r+=(a[b[y]]-a[b[x]])*(a[b[y]]-a[b[x]]);
            x++;
            y--;
            if (r>k) return 0;
        }
        if (r<=k) return true;else return false;
    }
    int main()
    {
        int t;
        cin>>t;
        while (t--)
        {
               cin>>n>>m>>k;
               for (int i=1;i<=n;i++) 
               cin>>a[i];
               int ans=0,l=1;
               while (l<=n)
               {
                      int num=1;
                      while (l+num<=n&&check(l,l+num)) num<<=1;
                      int x=l+num/2,y=l+num;
                      if (y>n) y=n;
                      tj=0;
                      for (int i=l;i<=y;i++) 
                      b[++tj]=i;
                      sort(b+1,b+tj+1,cmp);
                      int now=x;
                      while (x<=y)
                      {
                             int mid=(x+y)>>1;
                             if (work(mid)) 
                             {
                                now=mid;
                                 x=mid+1;
                             }else y=mid-1;
                      }
                      ans++;
                      l=now+1;
               }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    0045算法笔记——【随机化算法】舍伍德随机化思想搜索有序表
    精进~如何成为很厉害的人
    哪些小习惯一旦养成终生受用?
    2016第24周四
    2016第24周三
    2016第24周二
    2016第24周一
    2016第23周日
    前端资源汇总
    2016第23周五
  • 原文地址:https://www.cnblogs.com/YYC-0304/p/9499902.html
Copyright © 2011-2022 走看看