樹狀陣列求逆序對

2021-09-17 21:44:17 字數 1671 閱讀 2556

題目:

分析:計算像a,b這樣上公升的有la對,像c,d這樣下降的有lb對,ans=la*lb。這樣是有重複的,重複的就是a與c重合,a與d重合,b與c重合,b與d重合這四種情況。那麼減去這四種情況就ok了。

可以用樹狀陣列預處理出每一位i的左邊比a[i]大的有多少la,少的有多少li,右邊比a[i]大的有多少ra,少的有多少li。最後ans減去ri[i]*ra[i];    li[i]*la[i];   li[i]*ri[i];   la[i]*ra[i]  就行了。

ac code:

#includeusing namespace std;

typedef long long ll;

const int maxn=5e4+5;

int b[maxn];

ll ll[maxn],lr[maxn],rl[maxn],rr[maxn];

int k;

struct node

return sum;

}ll c1[maxn],c2[maxn];

int cnt[maxn];///用於計算重複的數的個數

int main()

ll sum1=0,sum2=0;

for(int i=1;i<=n;i++)

memset(cnt,0,sizeof cnt);

for(int i=n;i>=1;i--)

ll ans=sum1*sum2;

for(int i=1;i<=n;i++)

printf("%lld\n",ans);

}return 0;

}

最後貼個樹狀陣列求逆序對的板子:

#include#include#include#include#define ll long long

using namespace std;

int n,tree[100010];

void add(int k,int num)}

int read(int k)

return sum;

}struct node

a[100010];

bool cmp(node a,node b)

int main(void)

sort(a+1,a+1+n,cmp);

int cnt = 1;

for(i=1;i<=n;i++)

ll sum = 0;

for(i=1;i<=n;i++)

printf("%lld\n",sum);

}return 0;

}

外加歸併排序求逆序對的板子:

#includeusing namespace std;

typedef long long ll;

const int maxn=1e5+5;

ll ans;

void merge(int a,int l,int mid,int r)

else

while(i<=mid) a[k++]=b[i++];

while(j<=r) a[k++]=b[j++];

}void divide(int a,int l,int r)

int main()

return 0;

}

樹狀陣列求逆序對

題目描述 給定乙個陣列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 這兩個就算一對逆序對,簡單來說,所有逆序對的個數和就是找每乙個數的前面有幾個比他的大的數,他們加起來的和就是逆序對的總數。知道什麼是逆序對後就好辦了,...

樹狀陣列 求逆序對

樹狀陣列可以解決線段樹能夠解決的問題,且更加節省空間。線段樹的講解 可以看這位大佬的部落格 樹狀陣列的講解 另一位大佬的部落格 這裡主要寫一下利用樹狀陣列來求解逆序對的個數。簡單來說就是一段序列裡面每個數所在位置之前的位置上比這個數大的數字個數之和。例如 1 2 3 5 4 只有 4 前面的 有乙個...