码迷,mamicode.com
首页 > 其他好文 > 详细

【NOIP】提高组2013 火柴排队

时间:2016-08-13 22:19:36      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

【算法】求逆序对(树状数组)(也可以用归并排序等)

【题解】

学自:http://blog.csdn.net/greatwjj/article/details/16808243

https://vijos.org/p/1842/solution(从下往上第三个回答)

技术分享

因此要使结果最小,只要最大化aibi(i=1...n),即使小的数对应小的数,大的数对应大的数。

1.对于数列a,b先离散化,将他们值替换为他们在所在数列的排名。

2.令数列c记录a中每个数应该在b中的位置(a的目标位置)。

3.对数列c求逆序对的数量。

技术分享
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lowbit(x) x&(-x)
using namespace std;
const int maxn=100010,mod=99999997;
struct cyc{int v,ord;}p[maxn],pa[maxn];
bool cmp(cyc a,cyc b){return a.v<b.v;}
int a[maxn],n,s[maxn];long long ans;
void give(int x)
{
    for(int i=x;i<=n;i+=lowbit(i))s[i]++;
}
int ask(int x)
{
    int anss=0;
    for(int i=x;i>0;i-=lowbit(i))anss+=s[i];
    return anss;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&pa[i].v),pa[i].ord=i;
    sort(pa+1,pa+n+1,cmp);
//         for(int i=1;i<=n;i++)a[pa[i].ord]=i;//printf("[a]");for(int i=1;i<=n;i++)printf("%d ",a[i]);printf("\n");
    for(int i=1;i<=n;i++)scanf("%d",&p[i].v),p[i].ord=i;
    sort(p+1,p+n+1,cmp);
    for(int i=1;i<=n;i++)a[pa[i].ord]=p[i].ord;         
//        printf("[b]");for(int i=1;i<=n;i++)printf("%d ",b[i]);printf("\n");
//        printf("[c]");for(int i=1;i<=n;i++)printf("%d ",a[i]);printf("\n");
    for(int i=1;i<=n;i++)
     {
        give(a[i]);
        (ans+=(i-ask(a[i])))%=mod;
     }
    printf("%lld",ans);
    return 0;
}
View Code

 

【NOIP】提高组2013 火柴排队

标签:

原文地址:http://www.cnblogs.com/onioncyc/p/5768905.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!