[機房練習賽] 題解 求逆序對
阿新 • • 發佈:2019-01-03
大家都很強, 可與之共勉。
如果你有一個長度為n 的序列:
a1; a2; a3; : : : ; an
那麼它的一個逆序對是一個二元組:< i; j > 滿足i < j 且ai > aj,其中i; j 2 [1; n]。
我們稱一個序列所包含的逆序對的個數為這個序列的逆序對數。
那麼問題來了:
我給出一個長度為n 的序列,需要你計算:
a1; a2 : : : an-1; an
a2; a3 : : : an; a1
a3; a4 : : : a1; a2
an; a1 : : : an-2; an-1
這n 個序列的逆序對之和。
Input
輸入檔案包含2 行:
第1 行1 個整數:n,表示給定序列的長度。
第2 行n 個整數:a1 a2 : : : an,表示初始序列。
Output
輸出n 個序列的逆序對的和。
Sample
rotinv.in
3
2 2 3
rotinv.out
6
以上樣例中,3 個序列分別是:2 2 3,2 3 2,3 2 2,分別有0,1,2 個逆序對,所以和為6。
rotinv.in
3
1 1 1
rotinv.out
0
以上樣例中,3 個序列都是:1 1 1,逆序對數為0,所以答案為0。
Note
• 對於30% 的資料,1 n 300
• 對於60% 的資料,1 n 5000
• 對於100% 的資料,1 n 106,1 ai n
#include "cctype"
#include "cstdio"
#include "cstring"
#include "algorithm"
#define lowbit(x) ((x) & (-x))
#define abs(a) ((a) < 0 ? (-(a)) : (a))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define rep(_, m, n) for(register int _ = (m); i <= (n); ++i)
#define res(_, n, m) for(register int _ = (n); i >= (m); --i)
#define edges(u) for(register int _ = head[u]; _; _ = g[i].pre)
template <class T>
inline bool readIn( T &x ) {
char ch;
T opt = 1;
while( !isdigit(ch = (char) getchar()) && (ch ^ -1) ) if( ch == '-' ) opt = -1;
if( !(ch ^ -1) ) return false;
for( x = ch - 48; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48 );
x *= opt;
return true;
}
template <class T>
inline void write( T x ) {
if( x > 9 )
write(x / 10);
putchar( x % 10 + 48 );
}
template <class T>
inline bool writeIn( T x ) {
if(x < 0) {
x = -x;
putchar('-');
}
write(x);
return true;
}
class io {
public:
#define SIM "rotinv"
io() {
freopen(SIM ".in", "r", stdin);
freopen(SIM ".out", "w", stdout);
}
~io() {
fclose(stdin);
fclose(stdout);
}
} WhiteBunny;
typedef long long LL;
const int MAXN = (int) 1e6 + 5;
int n, bit[MAXN], a[MAXN];
LL ans, cnt;
inline bool modify(int pos, int delta) {
for(register int i = pos; i <= n; i += lowbit(i))
bit[i] += delta;
}
inline LL query(int r) {
int rt = 0;
for(register int i = r; i; i -= lowbit(i))
rt += bit[i];
return rt;
}
int main() {
readIn(n);
rep(i, 1, n) readIn(a[i]);
rep(i, 1, n) {
cnt += (i - 1) - query(a[i]);
modify(a[i], 1);
}
rep(i, 1, n) {
modify(a[i], -1);
cnt += (n - 1) - query(a[i]);
cnt -= query(a[i] - 1);
modify(a[i], 1);
ans += cnt;
}
writeIn(ans);
putchar(10);
return 0;
}
程式碼騷起來
#include "cctype"
#include "cstdio"
#include "cstring"
#include "algorithm"
#define lowbit(x) ((x) & (-x))
#define abs(a) ((a) < 0 ? (-(a)) : (a))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define rep(_, m, n) for(register int _ = (m); i <= (n); ++i)
#define res(_, n, m) for(register int _ = (n); i >= (m); --i)
#define edges(u) for(register int _ = head[u]; _; _ = g[i].pre)
template <class T>
inline bool readIn( T &x ) {
char ch;
T opt = 1;
while( !isdigit(ch = (char) getchar()) && (ch ^ -1) ) if( ch == '-' ) opt = -1;
if( !(ch ^ -1) ) return false;
for( x = ch - 48; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48 );
x *= opt;
return true;
}
template <class T>
inline void write( T x ) {
if( x > 9 )
write(x / 10);
putchar( x % 10 + 48 );
}
template <class T>
inline bool writeIn( T x ) {
if(x < 0) {
x = -x;
putchar('-');
}
write(x);
return true;
}
class io {
public:
#define SIM "rotinv"
io() {
freopen(SIM ".in", "r", stdin);
freopen(SIM ".out", "w", stdout);
}
~io() {
fclose(stdin);
fclose(stdout);
}
} WhiteBunny;
typedef long long LL;
const int MAXN = (int) 1e6 + 1;
int n, bit[MAXN], a[MAXN];
LL ans, cnt;
inline bool modify(int pos, int delta) {
for(register int i = pos; i <= n; i += lowbit(i))
bit[i] += delta;
}
inline int query(int r) {
int rt = 0;
for(register int i = r; i; i -= lowbit(i))
rt += bit[i];
return rt;
}
int main() {
readIn(n);
rep(i, 1, n) readIn(a[i]), cnt += (i - 1) - query(a[i]), modify(a[i], 1);
rep(i, 1, n)
modify(a[i], -1), (cnt += (n - 1) - query(a[i])) -= query(a[i] - 1),
modify(a[i], 1), ans += cnt;
writeIn(ans);
putchar(10);
return 0;
}