zoukankan      html  css  js  c++  java
  • Gym

    题意:有一个长度为n的序列,你每次可以选择两个相邻的元素交换,求把这个序列排成单峰序列的最少交换次数。

    方法一:将元素按数值从大到小排序(保存原来的位置),把最大的插在中间,剩下的依次往两边放,依次考虑每个数该放在左边还是右边,只考虑后加入的数对已有的数的贡献。由于前面加入的数的次序对后加入的数无影响,因此贪心地选择贡献小的一边就行了。贡献为重排后下标的逆序数,注意大小相同的要特殊处理一下就行了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 struct D {
     6     int x,y;
     7     bool operator<(const D& b)const {return x>b.x;}
     8 } a[N];
     9 int c[N],n;
    10 int lb(int x) {return x&-x;}
    11 void add(int u,int x) {for(; u<N; u+=lb(u))c[u]+=x;}
    12 int get(int u) {int ret=0; for(; u; u-=lb(u))ret+=c[u]; return ret;}
    13 int main() {
    14     scanf("%d",&n);
    15     for(int i=0; i<n; ++i)scanf("%d",&a[i].x),a[i].y=i+1;
    16     sort(a,a+n);
    17     ll ans=0;
    18     for(int i=0,j,k; i<n; i=j) {
    19         for(j=i; j<n&&a[j].x==a[i].x; ++j);
    20         for(k=i; k<j; ++k) {
    21             int t=get(a[k].y);
    22             ans+=min(t,i-t);
    23         }
    24         for(k=i; k<j; ++k)add(a[k].y,1);
    25     }
    26     printf("%lld
    ",ans);
    27     return 0;
    28 }

    方法二:通过观察可以发现:

    1.把一个元素通过相邻交换的方式移动到其他地方,其他元素的相对位置不变

    2.对于单峰序列,比某个元素大的数必定都在该元素的同侧

    因此,对于每个元素而言,要么把它左边比它大的元素都移到右边去,要么把它右边比它大的元素都移到左边来,因此每个元素对答案的贡献为min(左边比它大的元素数,右边比它大的元素数),树状数组左右各扫一遍就行了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e5+10;
     5 int L[N],R[N],c[N],n,a[N];
     6 int lb(int x) {return x&-x;}
     7 void add(int u,int x) {for(; u<N; u+=lb(u))c[u]+=x;}
     8 int get(int u) {int ret=0; for(; u; u-=lb(u))ret+=c[u]; return ret;}
     9 int main() {
    10     scanf("%d",&n);
    11     for(int i=0; i<n; ++i)scanf("%d",&a[i]);
    12     for(int i=0; i<n; ++i)L[i]=i-get(a[i]),add(a[i],1);
    13     memset(c,0,sizeof c);
    14     for(int i=n-1; i>=0; --i)R[i]=n-1-i-get(a[i]),add(a[i],1);
    15     ll ans=0;
    16     for(int i=0; i<n; ++i)ans+=min(L[i],R[i]);
    17     printf("%lld
    ",ans);
    18     return 0;
    19 }
  • 相关阅读:
    下载MySQL数据库
    2012开源项目计划-WPF企业级应用整合平台
    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
    WPF入门教程系列(一) 创建你的第一个WPF项目
    一、什么是WPF?
    asp.net页面间传值的几种方法
    .NET 代码编译过程
    全面认识.NET框架(一)
    C#里partial关键字的作用(转摘)
    .NET概念:.NET程序编译和运行
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11394132.html
Copyright © 2011-2022 走看看