zoukankan      html  css  js  c++  java
  • 【JZOJ6292】序列【思维】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/6292
    在这里插入图片描述


    思路:

    这道题移动数字不是很好办,考虑移动下标,这样和移动数字是等价的。
    如果第ii个数字的下标移动到了i+1i+1,那么原来的aii|a_i-i|就变成了aii1|a_i-i-1|,那么原来aiia_ileq i的贡献就增加了1,ai>ia_i>i的贡献就减少了1。
    所以我们需要记录下每一个时刻有多少个aiia_ileq i,同时又有多少个ai>ia_i>i。考虑到在移动下标时aia_iii的大小关系可能是会变的,所以我们需要开一个桶来记录移动了ii个单位后,有多少的大小关系会变动。
    这样就做到了每次O(1)O(1)修改,时间复杂度O(n)O(n)


    代码:

    #include <cstdio>
    #include <string>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N=5000010;
    int n,s1,s2,a[N],t[N];
    ll ans,minn;
    
    int read()
    {
    	int d=0; char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch))
    		d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    int main()
    {
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	n=read();
    	for (register int i=1;i<=n;i++)
    	{
    		a[i]=read();
    		if (a[i]>i)
    		{
    			s1++;
    			t[a[i]-i]++;
    			minn+=(ll)a[i]-i;
    		}
    		else
    		{
    			s2++;
    			minn+=(ll)i-a[i];
    		}
    	}
    	ans=minn;
    	for (register int i=1;i<=n;i++)
    	{
    		int k=n-i+1;
    		ans=ans+(ll)s2-s1;
    		ans=ans-(ll)(n-a[k]+1)+(ll)(a[k]-1);
    		if (a[k]<=1) s2++; 
    		else
    		{
    			s1++;
    			t[i+a[k]-1]++;
    		}
    		s2--;
    		s1-=t[i]; s2+=t[i];
    		minn=min(minn,ans);
    	}
    	printf("%lld",minn);
    	return 0;
    }
    
  • 相关阅读:
    oracle 之监听保护
    游戏升级之路
    《C++游戏开发》十六 游戏中的寻路算法(二):迷宫&A*算法基础
    【JavaScript】实现复选框的全选、全部不选、反选
    虎嗅: 小米盒子vs乐视盒子
    即将成为传奇的微软
    DB-Oracle-DatabaseLinks:百科
    人物-思想家-默罕默德:百科
    ADO.NET:目录
    ADO.NET:百科
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998035.html
Copyright © 2011-2022 走看看