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