【洛谷P1774】最接近神的人_NOI导刊2010提高(02)

题目描述

破解了符文之语,小FF开启了通往地下的道路。当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案。而石门上方用古代文写着“神的殿堂”。小FF猜想里面应该就有王室的遗产了。但现在的问题是如何打开这扇门……

仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的。而最聪明的人往往通过一种仪式选拔出来。仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素。而用最少的交换次数使原序列变成不下降序列的人即是下一任智者。

小FF发现门上同样有着n个数字。于是他认为打开这扇门的秘诀就是找到让这个序列变成不下降序列所需要的最小次数。但小FF不会……只好又找到了你,并答应事成之后与你三七分……

输入输出格式

输入格式:

第一行为一个整数n,表示序列长度

第二行为n个整数,表示序列中每个元素。

输出格式:

一个整数ans,即最少操作次数。

输入输出样例

输入样例#1:

4
2 8 0 3

输出样例#1:

3
   样例说明:开始序列为2 8 0 3,目标序列为0 2 3 8,可进行三次操作的目标序列:
    1.Swap (8,0):2  0  8  3
    2.Swap (2,0):0  2  8  3
    3.Swap (8,3):0  2  3  8

说明

对于30%的数据1≤n≤10^4。

对于100%的数据1≤n≤5*10^5;

-maxlongint≤A[i]≤maxlongint。

题解:

裸的逆序对问题,其实本题和codevs1688求逆序对是同一题,两题代码都一样。

归并排序求逆序对的模板,推荐一篇很好的归并排序求逆序对的文章:http://blog.csdn.net/acdreamers/article/details/16849761

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500000+5;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n;
int a[maxn],tmp[maxn];
ll ans;
inline void merge(int x,int mid,int y)
{
    int i=x,j=mid+1,k=x;
    while(i<=mid&&j<=y)
    {
        if(a[i]>a[j])
        {
            tmp[k++]=a[j++];
            ans+=mid-i+1;
        }
        else
        tmp[k++]=a[i++];
    }
    while(i<=mid) tmp[k++]=a[i++];
    while(j<=y) tmp[k++]=a[j++];
    for(int i=x;i<=y;i++) a[i]=tmp[i];
}
void merge_sort(int x,int y)
{
    if(x<y)
    {
        int mid=(x+y)>>1;
        merge_sort(x,mid);
        merge_sort(mid+1,y);
        merge(x,mid,y);
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    merge_sort(1,n);
    printf("%lld\n",ans);
    return 0;
}

归并排序求逆序对

树状数组求逆序对,本题有相同的情况,如果直接用sort函数会错的。

可以进行去重操作,但未免太麻烦,直接用stable_sort就行了,可以百度一下,与sort的区别就是不改变相同元素的位置,如果用sort会增添逆序对的个数,因为sort有可能改变相同元素的位置,那么相同元素有可能就成为了逆序对。

还有一种方法就是在自定义比较函数里面增加一个如果两个元素的值相等,那么比较两个元素的编号就行了。

具体操作看代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500000+5;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n;
int b[maxn],c[maxn];
struct node
{
    int x,id;
    bool operator < (const node &j) const {
        return x<j.x;
    }
}a[maxn];
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int d)
{
    while(x<=n)
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
inline int getsum(int x)
{
    int tmp=0;
    while(x)
    {
        tmp+=c[x];
        x-=lowbit(x);
    }
    return tmp;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].x=read();
        a[i].id=i;
    }
    stable_sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) b[a[i].id]=i;
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        update(b[i],1);
        ans+=i-getsum(b[i]);
    }
    printf("%lld\n",ans);
    return 0;
}
    

stable_sort

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=500000+5;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x*f;
}
int n;
int b[maxn],c[maxn];
struct node
{
    int x,id;
    bool operator < (const node &j) const {
        return (x==j.x? id<j.id : x<j.x);
    }
}a[maxn];
inline int lowbit(int x){return x&(-x);}
inline void update(int x,int d)
{
    while(x<=n)
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
inline int getsum(int x)
{
    int tmp=0;
    while(x)
    {
        tmp+=c[x];
        x-=lowbit(x);
    }
    return tmp;
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].x=read();
        a[i].id=i;
    }
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++) b[a[i].id]=i;
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        update(b[i],1);
        ans+=i-getsum(b[i]);
    }
    printf("%lld\n",ans);
    return 0;
}

自定义比较函数

时间: 2024-10-20 22:10:01

【洛谷P1774】最接近神的人_NOI导刊2010提高(02)的相关文章

洛谷P1774 最接近神的人_NOI导刊2010提高(02) [2017年6月计划 线段树03]

P1774 最接近神的人_NOI导刊2010提高(02) 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即

洛谷P1774 最接近神的人_NOI导刊2010提高(02)(求逆序对)

To 洛谷.1774 最接近神的人 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元

洛谷 P1774 最接近神的人_NOI导刊2010提高(02)

题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素.而用最少的交换次数使原序列变成不

洛谷——P1774 最接近神的人_NOI导刊2010提高(02)

https://www.luogu.org/problem/show?pid=1774 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的

P1774 最接近神的人_NOI导刊2010提高(02)

P1774 最接近神的人_NOI导刊2010提高(02) 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即

luogu P1774 最接近神的人_NOI导刊2010提高(02)

题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着"神的殿堂".小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门-- 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素.而用最少的交换次数使原

luoguP1774 最接近神的人_NOI导刊2010提高(02)x

P1774 最接近神的人_NOI导刊2010提高(02) 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即

洛谷 P1796 汤姆斯的天堂梦_NOI导刊2010提高(05)

P1796 汤姆斯的天堂梦_NOI导刊2010提高(05) 题目描述 汤姆斯生活在一个等级为0的星球上.那里的环境极其恶劣,每天12小时的工作和成堆的垃圾让人忍无可忍.他向往着等级为N的星球上天堂般的生活. 有一些航班将人从低等级的星球送上高一级的星球,有时需要向驾驶员支付一定金额的费用,有时却又可以得到一定的金钱. 汤姆斯预先知道了从0等级星球去N等级星球所有的航线和需要支付(或者可以得到)的金钱,他想寻找一条价格最低(甚至获得金钱最多)的航线. 输入输出格式 输入格式: 第一行一个正整数N(

洛谷P1774 最接近神的人

题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即交换序列中相邻的两个元素.而用最少的交换次数使原序列变成不