题意:求所有区间逆序对个数之和。
(n <= 10^6 , a[i] <= 10^9)所有数字均为非负整数。
题解:
对于一个逆序对((i,j)),其贡献为(i*(n-j+1))。这个很容易理解。
对于逆序对问题,我们通常使用树状数组进行求解。
于是他俩自然而然的结合起来了。然后我就mengbi了
对于一个位置(i),((n-i+1))是固定的,故树状数组维护的应为上文的(i)
需要注意:1.(a_i)值域过大,应离散化
2.答案过大,可用(\_\_int128)解决。
代码:
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
using namespace std;
unsigned long long t[1001000];
__int128 temp,ans;
int n,g;
struct data
{
int x,y,nx;
}a[1001000];
bool cmp(data x,data y)
{
return x.x<y.x;
}
bool cnp(data x,data y)
{
return x.y<y.y;
}
void add(int x,int y)
{
for (int i=x;i;i-=lowbit(i))
{
t[i]+=y;
}
}
__int128 ask(__int128 x)
{
if (x<=0) return 0;
__int128 s=0;
for (int i=x;i<=n;i+=lowbit(i))
{
s+=t[i];
}
return s;
}
void print(__int128 x)
{
string st="";
if (x==0) {cout<<"0
";return ;}
while (x)
{
st=char(x%10+'0')+st;
x/=10;
}
cout<<st<<endl;
}
int main()
{
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].y=i;
}
sort(a+1,a+n+1,cmp);
a[0].x=-1;
for (int i=1;i<=n;i++)
{
if (a[i].x==a[i-1].x) a[i].nx=g;
else a[i].nx=++g;
}
sort(a+1,a+n+1,cnp);
for (int i=1;i<=n;i++)
{
ans+=ask(a[i].nx+1)*(n-i+1);
add(a[i].nx,i);
}
print(ans);
return 0;
}