zoukankan      html  css  js  c++  java
  • NOIP2013火柴排队

    Solution

    恕我直言,这题是真的坑。

    对于这道题,一个很显然的思路是对于A B两个序列,他们交换完后相对的两个数在原序列中的相对大小是相同的,于是我们就把序列按照A排序,在把B离散化,求逆序对,诶,这题真水。

    期望得分100,实际得分10。

    WTF???我写挂了??

    正解,将A,B分别排序,c[a[i].pos]=b[i].pos,再将c求一波逆序对。

    为什么这样可以,而上一种做法不行?

    随便举个栗子

    2 4 5 6 1 3

    3 4 1 6 5 2

    这是离散化后的序列,我们固定A序列,让B序列动,那么对于B序列来说,3应当在第六个,4应当在2个,1应当在第五个,6应当在第四个,5应当在第三个,2应当在第一个。于是B序列就变成了

    6 2 5 4 3 1

    这就是正解的合理性,而错误解法通过直接排序,将相邻元素的相对顺序打乱了,导致求出的解一定是错的(但是样例都能过【喷血】)。

    Code

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define mod 99999997 
    #define N 100009
    using namespace std;
    long long n,tot,tr[N],c[N];
    long long ans;
    struct de
    {
    long long a,b;
    }a[N],b[N]; 
    void add(int u)
    {
    while(u<=n)
    {
    tr[u]++;
    tr[u]%=mod;
    u+=u&-u;
    }
    }
    long long q(int u)
    {
    long long an=0;
    while(u)
    {
    an+=tr[u];
    u-=u&-u;
    }
    return an;
    }
    bool cmp(de a,de b)
    {
    return a.a<b.a;
    }
    int main()
    {
    scanf("%lld",&n);
    for(int i=1;i<=n;++i)
    scanf("%lld",&a[i].a),a[i].b=i;
    for(int i=1;i<=n;++i)
    scanf("%lld",&b[i].a),b[i].b=i;
    sort(a+1,a+n+1,cmp);
    sort(b+1,b+n+1,cmp);
    for(int i=1;i<=n;++i)
    c[a[i].b]=b[i].b;
    for(int i=1;i<=n;++i) 
    {
    (ans+=i-q(c[i])-1)%=mod;
    add(c[i]);
    }
    // for(int i=1;i<=n;++i)
    // cout<<c[i]<<" ";
    cout<<ans;
    return 0;
    }



    最后一句话

    Think twice,code once

  • 相关阅读:
    线程池进程池
    设计原则与设计模式
    腾讯阿里第三方接入
    计划任务
    系统服务
    Python Faker模块
    Python openpyxl模块
    Python-docx模块
    进程管理
    磁盘管理
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/9389192.html
Copyright © 2011-2022 走看看