zoukankan      html  css  js  c++  java
  • CH109 Genius ACM 题解报告

    题目传送门

    【题目大意】

    【思路分析】

    首先显然可知,当一段区间内选出的$M$对数分别是,最大和最小一对,次大和次小一对,……,第$M$大和第$M$小一对,此时的“校验值”最大,如果这段区间的最大“校验值”满足条件了,那么这个区间就是合法的。我们考虑将数列$A$从头开始分段,在满足每段区间合法的情况下让区间尽量包含更多的数,到达结尾时整个数组分成的段数就是答案。

    于是我们要解决的问题就是,当确定一个区间的左端点$L$后,右端点$R$在满足$A[L]~A[R]$的“校验值”不超过$T$的情况下,最大能取到多少。

    求长度为$N$的一段区间的“校验值”需要排序配对,时间复杂度为$O(N*log_2N)$。当“校验值”上限$T$比较小时,如果在整个$L~N$的区间上二分右端点$R$,二分的第一步就要检验$(N-L)/2$这么长的一段,最终右端点$R$却可能只扩展了一点,浪费了很多时间,于是我们考虑使用倍增算法。

    倍增过程如下:

    1.初始化:$p=1,R=L$

    2.求出$[L,R+p]$这一段区间的“校验值”,若$le T$,则$R+=p,p*=2$,否则$p/=2$

    3.重复上一步,直到$p$的值变为0,此时$R$即为所求

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define rg register
     5 #define ll long long
     6 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     7 using namespace std;
     8 const int N=500002;
     9 int K,n,m,a[N],b[N],c[N];
    10 ll t;
    11 bool check(int l,int mid,int r){
    12     go(i,mid,r) b[i]=a[i];
    13     sort(b+mid,b+r+1);
    14     int i=l,j=mid;
    15     go(k,l,r)
    16         if((i<=mid-1&&b[i]<b[j])||j>r) c[k]=b[i++];
    17         else c[k]=b[j++];
    18     i=l,j=r;int num=min(m,(r-l+1)/2);ll sum=0;
    19     while(num--)
    20         sum+=(ll)(c[i]-c[j])*(c[i]-c[j]),i++,j--;
    21     if(sum<=t){
    22         go(i,l,r) b[i]=c[i];
    23         return 1;
    24     }
    25     return 0;
    26 }
    27 int main(){
    28     scanf("%d",&K);
    29     while(K--){
    30         scanf("%d%d%lld",&n,&m,&t);
    31         go(i,1,n) scanf("%d",&a[i]);
    32         int l=1,r=1,p=1,ans=0;b[1]=a[1];
    33         while(l<=n){
    34             if(r+p<=n&&check(l,r+1,r+p)) r+=p,p*=2;
    35             else p/=2;
    36             if(!p||r==n) ans++,l=++r,p=1,b[l]=a[l];
    37         }
    38         printf("%d
    ",ans);
    39     }
    40     return 0;
    41 }
    代码实现
  • 相关阅读:
    Mysql之锁、事务绝版详解干货!
    SSL基础知识(比较清楚)
    数字证书使用流程指南
    HTTPS与SSL
    IIS 6.0 Web园(Web Garden)
    验证数字可以有千分符可以有0个1个小数点小数点后输入后四舍五入保留两位(写个js验证真费劲)
    线程安全
    利用SSL给IIS加把锁(转)
    弹出div后其它不能操作(小技巧)
    关于反射
  • 原文地址:https://www.cnblogs.com/THWZF/p/11276206.html
Copyright © 2011-2022 走看看