• [CF819B] Mister B and PR Shifts


    题目

    原题链接

    解说

    第一思路暴力,时间效率(O(n^2)),肯定(T)这次试都没试,想办法优化吧。
    (O(n^2))的效率是因为我们有两层循环:枚举哪一位移动到队首了,以及计算现在的偏移值。枚举估计是省不了,那么我们就要想办法把计算偏移值优化到常数级,这样时间效率为(O(n)),应该问题不大了。
    我们可以注意到,每次移动时,如果原来(a[i]<=i),由于(a[i])对应的(i),变大了,所以(a[i]-i)负的更多了,绝对值变大了,且每移动一位每个数的绝对值增大(1);相对的,对于(a[i]>i),由于(i)增大了,绝对值每个数减小(1),因此每次操作我们只需让(sumpositive)减去(cntpositive),让(sumnegative)加上(cntnegative),之后要更新(cntpositive)(cntnegative)的值。位于队末的元素比较特殊,它的(i)(n)变成了(1),需要特殊处理一下。这样的话我们就把时间效率降到(O(n))了。
    有一个小方法需要说一下,就是我们怎么判断一个差为正的数何时转为差为负的数(指小于等于零)。枚举是不可能的,这样时间效率就又回(n^2)了。想一下,如果一个数正出来(x),那么就一定会在(x)轮之后转负(当然是指没有被扔到队首的情况,这时候我们特殊处理即可),因此我们在开始输入时就统计出来一个(count)数组统计每个正出来的数的(x)值即可。
    一些我踩的坑和部分注解在代码里给出。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2000000+3;
    typedef long long ll;
    ll n,a[1000000+3],sump,sumn,pos,ans,cntp,cntn,Count[maxn];
    //注意maxn不是n的范围,Count的下标是差的值,因此应开到差的最大值
    int main(){
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    		if(a[i]<=i){
    			cntn++;
    			sumn+=i-a[i];
    		}
    		else{
    			cntp++;
    			sump+=a[i]-i;
    			Count[a[i]-i]++;
    		}
    	}
    	ans=sump+sumn;
    	pos=0;//注意这里的初始化,一定记得把pos初始化为0,代表不用操作的情况
    	for(ll i=1;i<=n-1;i++){
    		sump-=cntp;
            cntp-=Count[i];
            sumn+=cntn;
            cntn+=Count[i];
            sumn-=n+1-a[n-i+1];
    		cntn--;
            if(a[n-i+1]>1){
    			Count[a[n-i+1]-1+i]++;
    			sump+=a[n-i+1]-1;
    			cntp++;
    		}
            else cntn++;
    		if(sumn+sump<ans){
    			ans=sumn+sump;
    			pos=i;
    		}
    	}
    	printf("%lld %lld",ans,pos);
    	return 0;
    }
    

    幸甚至哉,歌以咏志。

  • 相关阅读:
    在千万级的数据库查询中,如何提高效率?
    SQL的触发器和存储过程详解
    如何提高mysql的安全性?
    mysql的触发器
    HDU5564 Clarke and digits
    JOI2014Final 飞天鼠
    Topcoder10073 SRM418 BarracksEasy
    Topcoder9902 SRM416 DancingCouples
    Topcoder8307 SRM390 SetOfPatterns
    POJ1741 Tree(点分治)
  • 原文地址:https://www.cnblogs.com/DarthVictor/p/12853342.html
Copyright © 2020-2023  润新知