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; }