您的位置:首页 > 其它

怀念一下归并+逆序对

2016-05-27 10:55 155 查看
/*
codevs 4163 神犇与逆序对
*/
#include<cstdio>
#define ll long long
#define maxn 1000010
using namespace std;
ll n,a[maxn],b[maxn],ans;
ll init()
{
ll x=0;char s;s=getchar();
while(s<'0'||s>'9')s=getchar();
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x;
}
void Merge_sort(ll l,ll r)
{
if(l==r)return ;
ll mid=(l+r)/2;
Merge_sort(l,mid);
Merge_sort(mid+1,r);
ll i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(a[i]>a[j])
{
b[k++]=a[j++];ans+=mid-i+1;
}
else b[k++]=a[i++];
}
while(i<=mid)b[k++]=a[i++];
while(j<=r)b[k++]=a[j++];
for(ll i=l;i<=r;i++)a[i]=b[i];
}
int main()
{
n=init();
for(ll i=1;i<=n;i++)
a[i]=init();
Merge_sort(1,n);
printf("%lld\n",ans);
return 0;
}/*


/*
codevs 3286 火柴排队
首先要知道两点 1:两列火柴高度排名大小相同时排列答案最优 2:移动两个序

列和移动一个序列步数一样
证明嘛 自己想吧 ^ ^ 假设我们只移动第二个序列 消耗步数就是求下逆序对
现在的问题就是求出第二个序列需要怎么移动
求逆序对我们想到用归并排序 那么移动的目标就是有序序列1-n
怎么和“两列火柴高度排名大小相同”联系起来呢
这样 我们维护a1 a2 p1 p2几个序列
a1[i]=j:原序列1中i位置处的高度排名 a2同理
p1[i]=j:原序列1中高度排名i的位置
那p1[a2[i]]就是原序列2中i位置处的高度排名那么大的在1中的位置
我们把这个位置记在p2[i]中 那就是需要把i移动到p2[i] 也就是逆序对的个数
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define mod 99999997
#define maxn 2000020
using namespace std;
int n,a1[maxn],a2[maxn],p[maxn],l[maxn],w[maxn];
long long ans;
struct node
{
int o,h;
}s1[maxn],s2[maxn];
int init()
{
int x=0;char s;s=getchar();
while(s<'0'||s>'9')s=getchar();
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
return x;
}
int cmp(const node &x,const node &y)
{
return x.h<y.h;
}
void Merge(int l,int r)
{
if(l==r)return ;
int mid=(l+r)/2;
Merge(l,mid);
Merge(mid+1,r);
int i=l,j=mid+1,k=l;
while(i<=mid&&j<=r)
{
if(p[i]>p[j])
{
w[k++]=p[j++];ans=(ans+mid-i+1)%mod;
}
else w[k++]=p[i++];
}
while(i<=mid)w[k++]=p[i++];
while(j<=r)w[k++]=p[j++];
for(int i=l;i<=r;i++)p[i]=w[i];
}
int main()
{
n=init();
for(int i=1;i<=n;i++)
{
s1[i].h=init();
s1[i].o=i;
}
for(int i=1;i<=n;i++)
{
s2[i].h=init();
s2[i].o=i;
}
sort(s1+1,s1+1+n,cmp);
sort(s2+1,s2+1+n,cmp);
for(int i=1;i<=n;i++)
{
a1[s1[i].o]=i;
a2[s2[i].o]=i;
}
for(int i=1;i<=n;i++)
l[a1[i]]=i;
for(int i=1;i<=n;i++)
p[i]=l[a2[i]];
Merge(1,n);
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: