貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為「逆序對」的東西,這東西是這樣定義的:對於給定的一段正整數序列,逆序對就是序列中ai>aj且i輸入格式:
第一行,乙個數n,表示序列中有n個數。
第二行n個數,表示給定的序列。序列中每個數字不超過 10^9109
輸出格式:
給定序列中逆序對的數目。
輸入樣例#1:
輸出樣例#1:6
5 4 2 6 3 1
11
對於25%的資料,2500n≤2500
對於50%的資料, 10^4n≤4×104 。
對於所有資料,10^5n≤5×105
解法:分治(divide and conquer)
對於乙個大問題,把它分解為形式相同規模較小的問題,直到分解為可以處理的最小的子問題再進行合併即為原問題的解。
這個問題可以將歸併排序的演算法進行修改,每次歸併前的左半部分和右半部分都是排好序的序列,只需要掃一遍就可以找出逆序對的個數。
即:逆序對的個數等於兩者各自的逆序對和從這兩部分中各取乙個數組成的逆序對,然後就可以了。
時間複雜度為o(nlogn)
#include #define pii pair#define ll long long
using namespace std;
const int maxn = 1e6 + 10;
int a[maxn];
int tmp[maxn];
ll cnt;
void count(int l, int t, int r)
}i = l;j = t + 1;
int idx = l;
while(i <= t && j <= r)
else if(a[i] <= a[j])
}if(i == t + 1)
while(j <= r)
tmp[idx++] = a[j++];
if(j == r + 1)
while(i <= t)
tmp[idx++] = a[i++];
for(int i = l; i <= r; i++)
a[i] = tmp[i];
}void solve(int l, int r)
}int main()
洛谷 P1908 逆序對
題目描述 貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為 逆序對 的東西,這東西是這樣定義的 對於給定的一段正整數序列,逆序對就是序列中ai aj且i var i,n,t longint ...
洛谷 P1908 逆序對
貓貓tom和小老鼠jerry最近又較量上了,但是畢竟都是成年人,他們已經不喜歡再玩那種你追我趕的遊戲,現在他們喜歡玩統計。最近,tom老貓查閱到乙個人類稱之為 逆序對 的東西,這東西是這樣定義的 對於給定的一段正整數序列,逆序對就是序列中ai aj且i 輸入格式 第一行,乙個數n,表示序列中有n個數...
洛谷 P1908 逆序對
p1908 逆序對 法一 歸併排序求逆序對 不好理解,記一下 此處用的是從大到小排序,畢竟求的是序列中ai aj且i 在二路歸併的時候,設l i mid,mid 1 j r,要歸併的是a l 到a mid 還有a mid 1 到a r 只考慮a l 到a r 間產生的逆序對。在某時刻,要將a i 或...