• [JZO6401]:Time(贪心+树状数组)


    题目描述

      小$A$现在有一个长度为$n$的序列${x_i}$,但是小$A$认为这个序列不够优美。
      小$A$认为一个序列是优美的,当且仅当存在$kin [1,n]$,满足:
    $$x_1leqslant x_2leqslant...leqslant x_kgeqslant x_{k+1}geqslant...geqslant x_n$$
      现在小$A$可以进行若干次操作,每次可以交换序列中相邻的两个项,现在他想知道最少操作多少次之后能够使序列变为优美的。


    输入格式

      第一行一个正整数$n$,表示序列的长度。
      接下来一行$n$个整数,表示初始的序列。


    输出格式

      输出一行一个整数,表示最少需要的操作次数。


    样例

    样例输入:

    5
    3 4 5 1 2

    样例输出:

    1


    数据范围与提示

      对于$30\%$的数据,$nleqslant 12$
      对于$60\%$的数据,$nleqslant 100,000$,$a_i$互不相同
      对于$100\%$的数据,$n,a_ileqslant 100,000$


    题解

    考虑贪心,一定是挨个将最小的数移到两端不劣。

    至于过程直接用树状数组维护就好了,交换次数就是一侧比它大的数的个数。

    时间复杂度:$Theta(nlog n)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    int a[100001],cnt;
    int tr[100001];
    long long ans;
    vector<int> vec[100001];
    int lowbit(int x){return x&-x;}
    void add(int x){for(int i=x;i<=n;i+=lowbit(i))tr[i]++;}
    void del(int x){for(int i=x;i<=n;i+=lowbit(i))tr[i]--;}
    int ask(int x){int res=0;for(int i=x;i;i-=lowbit(i))res+=tr[i];return res;}
    int main()
    {
    	scanf("%d",&n);cnt=n;
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(int i=1;i<=n;i++){add(i);vec[a[i]].push_back(i);}
    	for(int i=1;i<=n;i++)
    		for(int j=0;j<vec[i].size();j++)
    		{
    			int x=ask(vec[i][j]-1),y=cnt-x-1;
    			ans+=min(x,(int)(y-vec[i].size()+j+1));
    			del(vec[i][j]);cnt--;
    		}
    	printf("%lld",ans);
    	return 0;
    }
    

    rp++

  • 相关阅读:
    云服务器Ubuntu更改默认python版本
    例题4-1-3-古老的密码、刽子手的游戏,救济金发放
    Github pages和Hexo搭建自己的博客
    Python字典基本操作介绍
    python win32api win32gui win32con PyUserInput实现自动化脚本
    spring--分类索引
    目录-java并发基础知识
    【转】集群单点故障的应对策略
    CnBlogs自定义博客样式
    读书笔记——《redis入门指南(第2版)》第七章 持久化
  • 原文地址:https://www.cnblogs.com/wzc521/p/11813489.html
Copyright © 2020-2023  润新知