zoukankan      html  css  js  c++  java
  • 图论复习O

    题意:求p数组分别向右移0~k-1位(最后一个到第一个)时的值的最小值,并输出最小的k

    分析:不难想到要把n²的处理变成线性(也做过很多类似的题了)

    显然对于一个值pi来说,他会随着他所处的i的变化,从pi>i变成pi<i

    比如,原来是1 3 2 4 5序列,3原来在2号位,3>2,当i增加时,|pi-i|的值变小,也就是序列变成5 1 3 2 4,此时pi(3)已经与i(3)相等了

    再移一下位置,序列变成4 5 1 3 2,此时pi(3)已经小于i(4)了,也就是说,再往后移,|pi-i|的值会变大

    所以我们需要知道每个pi会在什么时候对结果的贡献从-1变成1,

    显然,对于一个数pi>i,他一定会在i'=pi-i时贡献转变,

    这里肯定又有人有疑问,那如果这个数循环回开头了呢?

    没错

    对于当前的i来说,原数组中p[n-i+1]会刚好被换到开头,显然他之前所做的贡献是n-p[n-i+1],然后转化成了p[n-i+1]-1,

    这已经不仅仅是-1变成1的变化了,所以要单独给他把答案加上p[n-i+1]*2-n-1

    但此时贡献为-1的个数也变化了,也就是说对于每个i来说,now为当前贡献为-1的数量,now-=b[i-1]-1

    其中b[i]表示k=i时贡献从-1变成1的数量,其实就是now要减去k=i-1时发生的贡献转变,再加上末尾跑到开头造成的转变

    当然,这个跑到开头的p[n-i+1]也还有再从-1变成1的机会,也就是当前时间i再加上p[n-i+1]-1,也就是在k=p[n-i+1]-1+i时,他会再从-1转成1

    最后推导一下当前的结果咋变,

    首先,ans要+=p[n-i+1]*2-n-1,当然贡献为-1的有now个,为+1的有n-now个,所以ans还要+=n-now*2,

    所以ans+=p[n-i+1]*2-now*2-1?

    这就错了,因为答案加上p[n-i+1]*2-n-1的这个-1与now更新时加的一算重了,

    所以ans+= p[n-i+1]*2-now*2

    代码:

    #include<cstdio>
    #include<cmath>
    using namespace std;
    
    #define ll long long
    
    const int maxn=1e6+1;
    
    int a[maxn];
    int b[maxn];
    
    int main()
    {
        int n,now;
        ll ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if(a[i]>=i) now++,b[a[i]-i]++;
            ans+=abs(a[i]-i);
        }
        ll minans=ans;
        int p=0;
        for(int i=1;i<=n-1;i++)
        {
            now-=b[i-1]-1;
            if(a[n-i+1]+i<n) b[a[n-i+1]-1+i]++;
            ans+=2ll*(a[n-i+1]-now);
            if(ans<minans) minans=ans,p=i;
        }
        printf("%lld %d",minans,p);
        return 0;
    }
  • 相关阅读:
    未能正确加载“Microsoft.VisualStudio.Editor.Implementation.EditorPackage”包
    Only one instance of a ScriptManager can be added to the page.
    springboot SSM
    spring mvc 请求转发和重定向
    Spring Boot 配置 Swagger2 接口文档引擎
    solr
    jQuery
    反向代理负载均衡-Nginx
    mybatis二级缓存
    Vue的路由
  • 原文地址:https://www.cnblogs.com/lin4xu/p/12854259.html
Copyright © 2011-2022 走看看