求逆序对(树状数组)

求逆序对

描述

给定一个序列a1,a2,…,an,如果存在iaj,那么我们称之为逆序对,求逆序对的数目  

输入

第一行为n,表示序列长度,接下来的n行,第i+1行表示序列中的第i个数。  
N<=10^5。Ai<=10^5 

输出

两行,第一行为所有逆序对总数,第二行为本质不同的逆序对总数。

输入

4 
3 
2 
3 
2 

输出

3
1
 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 #define mod 1000000009 
 4 #define lowbit(x) x&(-x) 
 5 using namespace std;
 6 ll n,sum[100005],b[100005],ans,num,f[100005],in[100005];
 7 struct data{
 8     ll v,id;
 9 }a[100005];
10 void add(ll x,ll val)
11 {
12     while(x<=100001)
13     {
14         sum[x]+=val;
15         x+=lowbit(x);
16     }
17 } 
18 ll ask(ll x)
19 {
20     ll ans=0;
21      while(x)
22      {
23          ans+=sum[x];
24          x-=lowbit(x);
25     }
26     return ans;
27 }
28 int main()
29 {
30     scanf("%lld",&n);
31     for(ll i=1;i<=n;i++)
32         scanf("%lld",&a[i].v);
33     for(ll i=1;i<=n;i++)
34     {
35         add(a[i].v,1);
36         ans+=i-ask(a[i].v);
37     }
38     memset(sum,0,sizeof(sum));
39     for(ll i=n;i>=1;i--)
40     {
41         if(in[a[i].v]==0)
42         {
43             add(a[i].v,1);
44             in[a[i].v]=1;
45         }
46         num-=f[a[i].v];
47         f[a[i].v]=ask(a[i].v-1);
48         num+=f[a[i].v];
49     }
50     printf("%lld\n%lld",ans,num);
51     return 0;
52 }

猜你喜欢

转载自www.cnblogs.com/sbwll/p/13191425.html