归并排序---求逆序对
引例--超级贞鱼(http://oi.nks.edu.cn/zh/Problem/Details?cid=496&tid=F)(https://www.lydsy.com/JudgeOnline/problem.php?id=4769)
超级贞鱼 |
超级贞鱼 | ||
|
问题描述
马达加斯加贞鱼是一种神奇的双脚贞鱼,它们把自己的智慧写在脚上——每只贞鱼的左脚和右脚上个有一个数。
有一天,K只贞鱼兴致来潮( 1<=k<=20^5),排成一列,从左到右第i只贞鱼会在右脚写Ai(1<=Ai<=10^9 ),左脚上写上i(1≤i≤K),
第二年,这K只贞鱼按右脚的数从小到大排成一列,然后,它们决定重编号,从左到右第i只贞鱼会在右脚上写上左脚的数,在左脚上写i,
第三年,它们按第二年的方法重排列、重编号......n年后( 1<=n<=10^5),对于从左到右第i和第j贞鱼,若i<j且第i只贞鱼右脚上的数比第j只贞鱼右脚上的数大,则称它们为一对“超级贞鱼”。
问一共有多少对“超级贞鱼”。
输入格式
一共3行,第一行一个正整数k(),
第二行k个数从左到右输入Ai( ),
第三行一个正整数n( )。
输出格式
一个整数,表示“超级贞鱼”对数。
样例输入
6
5 2 6 3 1 7
0
样例输出
7
提示
对于全部数据: Ai<=10^9。
30%的数据:n,k<=400;
70%的数据:n,k<=10000;
100%的数据:n,k<=200000;
直接求Ai逆序对
满分最快代码模板
#include<stdio.h> #include<bits/stdc++.h> using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline int rd(){ char ch=nc();int sum=0; while(!(ch>='0'&&ch<='9'))ch=nc(); while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc(); return sum; } int n,v[2000010],p[2000010]; ll ans; void solve(int l,int r) { if(l==r) return ; int mid=(l+r)>>1,i=l,h1=l,h2=mid+1; solve(l,mid),solve(mid+1,r); for(i=l;i<=r;i++) { if(h1<=mid&&(h2>r||v[h1]<=v[h2])) ans+=h2-mid-1,p[i]=v[h1++]; else p[i]=v[h2++]; } for(i=l;i<=r;i++) v[i]=p[i]; } int main() { n=rd(); int i; for(i=1;i<=n;i++) v[i]=rd(); solve(1,n); printf("%lld",ans); return 0; }