大家都很强, 可与之共勉。
如果你有一个长度为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;
}