BZOJ 4769: 超级贞鱼 逆序对 + 归并排序

手画几下序列的变换后发现逆序对数是恒定的,故只需对第 $0$ 年求逆序对即可.
树状数组会 $TLE$ 的很惨,需要用到归并排序来求逆序对.
其实就是省掉了一个离散化的时间,估计能比树状数组快一半的时间. 

#include <cstdio> 
#include <algorithm>
#include <cstring>  
#define N 2000004 
#define ll long long 
#define setIO(s) freopen(s".in", "r" , stdin) 
using namespace std; 
namespace IO 
{
    char *p1,*p2,buf[100000];
    #define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    int readint() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
    ll readll() {ll x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
}; 
ll re = 0; 
int a[N], bu[N], n ; 
void solve(int l , int r) 
{  
    if(l == r) return ; 
    int mid = (l + r) >> 1, tmp = 0, tl = l, tr = mid + 1;  
    solve(l, mid), solve(mid + 1, r);                 
    while(tl <= mid && tr <= r) 
    {
        if(a[tl] <= a[tr]) bu[++ tmp] = a[tl], ++tl;   
        else bu[++ tmp] = a[tr], ++tr , re += (ll) mid - tl + 1;             
    }
    while(tl <= mid) bu[++ tmp] = a[tl], ++tl;   
    while(tr <= r) bu[++tmp] = a[tr], ++tr;      
    for(int i = 1; i <= tmp ; ++ i) a[l + i - 1] = bu[i];        
}
int main() 
{ 
    using namespace IO; 
    // setIO("input"); 
    int i , j; 
    ll oo; 
    n = readint();
    for(i = 1 ; i <= n ; ++ i) a[i] = readint();    
    oo = readll();   
    solve(1, n), printf("%lld\n", re);    
    return 0;        
}

  

posted @ 2019-08-15 12:54  EM-LGH  阅读(192)  评论(0编辑  收藏  举报