zoukankan      html  css  js  c++  java
  • CF819B Mister B and PR Shifts(思维)

    做这题细节比较多,要想清楚实际的含义

    首先我们肯定是想着枚举看看把哪些提到最前面

    对于这题我们发现我们要维护的有两种情况,一种是相减小于0,一种是相减大于0

    因此我们分两种情况讨论,并且注意状态的变化,具体细节看代码注释

     #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<ll,ll> pll;
    const int N=2e6+10;
    const int inf=0x3f3f3f3f;
    const int mod=1e9+7;
    ll a[N],sign[N];//sign表示移动i次变成第二类点的个数
    int main(){
        ios::sync_with_stdio(false);
        int n;
        cin>>n;
        int i;
        ll pcnt=0,pres=0;
        ll ncnt=0,nres=0;
        for(ll i=1;i<=n;i++){
            cin>>a[i];
            if(a[i]<=i){
                ncnt++;
                nres+=(i-a[i]);
            }
            else{
                sign[a[i]-i]++;
                pcnt++;
                pres+=(a[i]-i);
            }
        }
        ll ans=pres+nres;
        ll k=0;
        for(i=1;i<n;i++){
            pres-=pcnt;//第一类答案都减
            pcnt-=sign[i];//失去变成第二类的
            nres+=ncnt;//第二类答案都是加
            ncnt+=sign[i];//多出来的第二类
            ll x=a[n-i+1];//最后一位移到队首
            ncnt--;
            nres-=(n+1-x);//因为先行计算,导致最后一位到了n+1处,我们先减去他的贡献后把他移到第一位
            if(x>1){
                pcnt++;
                pres+=(a[n-i+1]-1);
                sign[x-1+i]++;//如果他又变成了第二类点,那么要加上他之前移动的i步再计算
            }
            else{
                ncnt++;
            }
            if(ans>pres+nres){
                ans=pres+nres;
                k=i;
            }
        }
        cout<<ans<<" "<<k<<endl;
        return 0;
    }
    View Code
    没有人不辛苦,只有人不喊疼
  • 相关阅读:
    memwatch使用简化
    memwatch检测内存泄露
    mtrace检测内存泄露
    2.14 环境变量及参数
    设计模式[索引]
    二叉树遍历
    AppCan 双击返回按钮退出应用
    MySQL语句相关经验总结
    mysql连接失败或出现“Too many connections”错误
    让IE的Button自适应文字宽度兼容
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/13576115.html
Copyright © 2011-2022 走看看