• Arithmetic Operations (根号分治)


    题目大意:

      给你一个 序列 an , 你可以进行操作, 将ai 变成任意一个数字, 问你将这个序列弄成等差数列,需要的最小操作次数, n为10^5, ai 1-10^5.

    思路:

    • 直接搞不好下手, 考虑转化题意
    • ai + d*i, 有多少个这样相同的数 , 枚举D就行了, 用桶存每一个位置的数就行了
    • 这是暴力做法, n*d的时间复杂度
    • 继续观察,当 d 比较大时, 
    • 枚举每一个ai 当首项, 会发现 最多有 1e5/d 个数是合法的,因此可以对此进行优化
    • 弄一个阈值作为lim,将这道题分为2个部分, 小于lim的d, 直接暴力做, 
    • 大于lim的值, 就最多会有1e5/lim 的数可能合法 枚举每一个ai 当首项, 在枚举 后面1e5/lim 个数, 用一个桶来存 出现的 d , 看哪一个d出现的数量是最多的
    #define int long long
    #define B 30000000
    int n,a[100010],cnt[2*B+10],ans=1e16;
    signed main(){
        read(n);
        For(i,1,n) read(a[i]);
        For(i,-200,200){
            For(j,1,n) cnt[a[j]-i*j+B]++;
            int mx=0; For(j,1,n) ckmax(mx,cnt[a[j]-i*j+B]);
            For(j,1,n) cnt[a[j]-i*j+B]=0;
            ckmin(ans,n-mx);
        }
        For(i,1,n){
            For(j,i+1,min(n,i+500)) if((a[j]-a[i])%(j-i)==0) cnt[(a[j]-a[i])/(j-i)+B]++;
            int mx=0; For(j,i+1,min(n,i+500)) if((a[j]-a[i])%(j-i)==0) ckmax(mx,cnt[(a[j]-a[i])/(j-i)+B]);
            For(j,i+1,min(n,i+500)) if((a[j]-a[i])%(j-i)==0) cnt[(a[j]-a[i])/(j-i)+B]=0;
            ckmin(ans,n-mx-1);
        }
        cout<<ans<<endl;
    }
    View Code

    根号分治过程:

    • 弄出一个lim, 将这道题分为2个部分,分别做
    • 一般是一边是暴力,一边是更具这lim来优化时间复杂度

        想法就是: 枚举某个值时, 有些过程是否会更具这个值的变大而减少

  • 相关阅读:
    HTTP协议
    安全测试-渗透性测试
    网络安全、Web安全、渗透测试之笔经面经总结(三)
    Struts2拦截器再认识
    struts2.5+框架使用通配符与动态方法
    struts.xml配置详解
    代理概述
    Mybatis Plugin(拦截器)的开发
    详解环境搭建SSM
    mybatis-databaseIdProvider多数据库支持
  • 原文地址:https://www.cnblogs.com/Lamboofhome/p/16801865.html
Copyright © 2020-2023  润新知