a703 求逆序對 線段樹的解法

2021-09-28 10:05:21 字數 2279 閱讀 5599

time limit: 10 second

memory limit: 2 mb

問題描述

給定乙個序列a1,a2...an。如果存在i小於j 並且ai大於aj,那麼我們稱之為逆序對,求給定序列中逆序對的數目

第一行為n,表示序列長度,接下來的n行,第i+1行表示序列中的第i個數。

所有逆序對的總數

432

32

3
【題解】

n的最大值為10w。

如果用線段樹來解的話,求解的思路都相同。

我就直接複製前一篇的例子了。

比如3 2 8 5

將它們排序(從大到小)

8 5 3 2

先把8放進去(原來的位置是3)

但是在放之前,先檢查位置3之前有沒有其他數字放進去了(如果放進去了肯定是比8大的數字,但是它們的下標又小於3(逆序對!));

因為沒有

所以就把下標3對應的位置改為1;

即0 0 1 0

然後是第大的5(原來的位置是4)

則看看4前面有多少個元素已經放進去了(字首和!)。

發現有1個。則答案遞增1;

然後把arr[4] 改為1

即0 0 1 1

然後是第三大的數字3,它原來的位置是1,但是1前面沒有數字已經放進去。則不遞增答案。

最後是最小的元素2,它原來的位置就是2,然後位置2之前有乙個數字3已經放在了位置1.即下標1的字首和為1.則答案遞增1.

最後答案為2;

這裡實際上就是涉及到單節點的遞增問題。

只要在改動的時候往上更新節點就可以了。很簡單的線段樹模型。

然後字首和的話就是返回(1,pos)的和,線段樹記錄的是區間和的。

但是要注意乙個問題。就是出現相同數字的情況。

則我們在寫比較函式的時候,讓相同的數字,之前的位置大的放在後面。然後我們處理到連續的相同數字的時候。就記錄這是連續相同數字裡面的第i個。

在累加完字首和之後答案減去i-1,因為相同大小就不算逆序對了;

【**】

#include #include struct data2

;__int64 sum[400001] = ,ans = 0; //線段樹的陣列貌似不用開4倍。。感覺2.2倍就夠了。。

int n;

data2 a[100001];//以結構體的形式寫,比較好寫比較函式。

__int64 query(int l, int r, int begin, int end, int rt)//詢問區間(l,r),當前節點的區間為(begin,end),當前節點為rt.

int m = (begin + end) / 2;//獲取這個節點所代表的區間的中點

__int64 re = 0;

if (l <= m)//如果左半部分有一部分區間在這個節點的左半部分則加上那一部分(當然會一直縮小區間直到找到那塊區間為止)

re += query(l, r, begin, m, rt <<1);

if (m < r) //如果這個節點的區間的右半部分有一部分和所求區間有交集,則加上右半部分那段有交集的區間的和。

re += query(l, r, m+1, end, rt<<1|1);

return re;

}int cmp(const data2 &a, const data2 &b)//比較函式。

void updata(int p, int num, int begin, int end, int rt)//要讓陣列下標為p的節點遞增num,然後當前的節點所代表的區間為[begin,end],當前節點為rt

int m = (begin + end) / 2;//取得這個節點所代表的區間中點

if (p <= m)//如果這個下標在中點的左邊就往左遞迴節點

updata(p, num, begin, m, rt<<1);

else//否則往右遞迴節點

updata(p, num, m+1, end, rt<<1|1);

sum[rt] = sum[rt<<1] + sum[rt<<1|1];//因為子節點可能發生了改變,所以要更新當前節點的區間和。

}int main()

std::sort(a + 1, a + 1 + n, cmp);//進行從大到小排序

int now = 0;

for (int i = 1; i <= n; i++)//假設當前是連續相同的數字中第x個,則now始終等於x-1

printf("%i64d", ans);

return 0;

}

a703 求逆序對 線段樹的解法

time limit 10 second memory limit 2 mb 問題描述 給定乙個序列a1,a2.an。如果存在i小於j 並且ai大於aj,那麼我們稱之為逆序對,求給定序列中逆序對的數目 第一行為n,表示序列長度,接下來的n行,第i 1行表示序列中的第i個數。所有逆序對的總數 432 ...

a703 求逆序對

time limit 10 second memory limit 2 mb 問題描述 給定乙個序列a1,a2.an。如果存在i小於j 並且ai大於aj,那麼我們稱之為逆序對,求給定序列中逆序對的數目 第一行為n,表示序列長度,接下來的n行,第i 1行表示序列中的第i個數。所有逆序對的總數 432 ...

逆序對 線段樹解法

逆序對 線段樹解法 求逆序對問題是乙個十分經典的演算法問題,通常使用歸併排序解決,經gster大神指點,寫出了逆序對線段樹寫法,順便練了練線段樹。題目傳送門 1 2 segment tree 3author shhhs 42016 09 28 12 35 17 5 6 include bits st...