zoukankan      html  css  js  c++  java
  • D. Suit and Tie cf996

    这道题让我想起了以前一道变态题 round#324 的E题,ANTON AND LRA

    这道题比较变态的地方是让你输出变化的规则。

    但是仔细一想发现如果只挪每个需要向后移动的元素,就可以每次在不多移动的情况下将小于等于pos位置的元素移动到pos前面

    因为每个元素需要移动的距离是一定的,在只需要保证每次使需要向前移动的元素尽量靠近末位置,需要向后的元素最终会移动到自己的位置上

    这样每次从后面到前面确定一个位置,又使前面的部分达到了最优状态。

    一直不断向前推进,直到第一位被确定下来。

    然后就是这道题,一开始想到的贪心策略是相邻两个数字如果不同的话就找到那个距离第一个近,就交换哪个。

    这样每确定两个数字都能保证确定下来的数字最小,最后自然得到最优解。

    #include<bits/stdc++.h>
    using namespace std;
    int a[110];
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=2*n;i++)
           scanf("%d",&a[i]);
        long long res=0;
        for(int i=1;i<=2*n;i+=2)//切忌低级错误!!! 
        {
            int j=i+1;
            if(a[j]==a[i])
              continue;
            int j1=i+2;
            int step1=1;
            while(a[j1]!=a[i]) j1++,step1++;
            int j2=i+2;
            int step2=2;
            while(a[j2]!=a[i+1]) j2++,step2++;
            if(step1<=step2)
            {
                for(int k=j1;k>i+1;k--)
                   swap(a[k],a[k-1]),res++;
            }
            else
            {
                swap(a[i],a[i+1]);
                res++;
                for(int k=j2;k>i+1;k--)
                   swap(a[k],a[k-1]),res++;
            }
        }
        printf("%lld
    ",res);
    }

    但是还不够简单,最简单的方法是,找到和第一个数字相同的元素,直接一个个交换过去

    为什么正确呢

    因为每次都考虑如果需要移动的数字不在两个数字中间,则不影响结果。

    如果在两个数字中间,就使得结果减一

    而每次向前移动,一定会使每对和他相交的数字结果减一

    int main(){
        scanf("%d", &n);
        for(int i = 1; i <= 2 * n; i++) {
            scanf("%d", &a[i]);
            if(!l[a[i]]) l[a[i]] = i;
            else r[a[i]] = i;
        }
    
        for(int i = 1; i <= n; i++) {
            ans += r[i] - l[i] - 1;
        }
    
        for(int i = 1; i <= n; i++) {
            for(int j = i + 1; j <= n; j++) {
                if(l[i] < l[j] && l[j] < r[i] && r[i] < r[j]) ans--;
                if(l[j] < l[i] && l[i] < r[j] && r[j] < r[i]) ans--;
            }
        }
        printf("%d
    ", ans);
        return 0;
    }

    这种移动数字的贪心很难找到证明方法,搞懂他们的证明很费劲

    其中比较关键的突破点就是有很多种方法都可以满足要求,而个数字的移动步数都是一定的,贪心时要保证在移动当前数字时,其他数字的距离可能不变,也可能变小。

    不变的不要增大,尽量让结果达到最优

    所以以后碰到这种题目,看懂贪心策略后尽量先记下来,为以后碰到类似题目找灵感,最后需要知道证明方法时再想着去证明

  • 相关阅读:
    RNA velocity | RNA速率
    Dynamic networks | 动态网络
    Scale Free Network | 无标度网络
    GO | KEGG的注释是怎么来的?
    Nearest neighbor graph | 近邻图
    L0 Regularization
    Median absolute deviation | Singular Value Decomposition奇异值分解 | cumulative sums |
    Multivariate normal distribution | 多元正态分布
    相似性 similarity | Pearson | Spearman | p-value | 相关性 correlation | 距离 distance | distance measure
    Type I and type II errors | 第一类错误和第二类错误
  • 原文地址:https://www.cnblogs.com/lishengkangshidatiancai/p/10351231.html
Copyright © 2011-2022 走看看