#include#includeusing namespace std;
int a[100001],n,temp[100001];
long long ct=0;
void merg(int first,int last)else
}//把剩下的按序放進陣列。
while(i<=mid)
while(j<=n)
for(int u=first;u<=last;u++)
a[u]=temp[u];
}void mergesort(int first,int last)
mergesort(0,n-1);
cout《我寫的二分的方法,但是會超時。。。然後看了大佬們的樹狀陣列,又複習了樹狀陣列,它是便於查詢與更新,m次更新複雜度為mlgn,時間複雜度低,效率高,c[i]的意思是它包括從i起(包括i)的lowbit(i)[i&-i],個數的和,-i表示取反加一。
大佬ac鏈結1
大佬ac鏈結2 樹狀陣列詳解
/* 用樹狀陣列求逆序數:陣列a代表數字i是否在序列中出現過,
如果陣列i已經存在於序列中,則a[i]=1,否則a[i]=0,
此時query(i)返回值為在序列中比數字i小的元素的個數,
假設序列中第i個元素的值為a,
那麼前i個元素中比i大的元素的個數為i-query(a).
*/
#include #include #define maxn 100000
using namespace std;
int n,tree[maxn];
int lowbit(int i)
void update(int i,int x)
} int query(int n)
return sum;
} int main ()
printf("%d\n",ans);
} return 0;
}
ps:我真的是不太明白這一句:ans+=i-query(a);
真的不明白,query(a)表示到a為止的,不明白,再想想。。。。
明白了:
query(a)表示輸入當前的狀態時,比a小的元素的個數,那麼用i(當前計算元素所處的位置),減去小於它的元素個數,剩下的便是大於等於它的元素個數,那麼就求出了當前數的逆序,對每乙個輸入的數,做判斷。
求序列的逆序對每個數求其左邊大於它的元素的個數。該演算法的複雜度o(nlogn),對n個數進行遍歷,更新樹狀陣列複雜度為logn。
樹狀陣列求逆序數
逆序數就是數中各位在它前面有多少個數比它大,求出這些元素個數之和。今天看了個樹狀陣列,可以很好的解決這個問題,普通方法需要o n 2 複雜度,用樹狀陣列只需要o nlongn 樹狀陣列實際上還是乙個陣列,只不過它的每個元素儲存了跟原來陣列的一些元素相關的結合值。若a為原陣列,定義陣列c為樹狀陣列。c...
樹狀陣列求逆序對
題目描述 給定乙個陣列a,它包含n個整數,分別是a 1 a 2 a n 如果存在下標i和j,使得 i j 且 a i a j 同時成立,則 i,j 就為乙個 逆序對 那麼a陣列總共有多少對不同的 逆序對 輸入格式 1247.in 第一行為n 1 n 100000 接下來是n行,每行乙個長整型範圍內的...
樹狀陣列求逆序對
很久以前就學了樹狀陣列,也知道可以用來求逆序對,然而一直沒弄明白他是怎麼實現的 可能當時沒搞清楚逆序對是什麼吧。逆序對就是如果i j a i a j 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...