这里先给出 __int128和利用vector的unqiue 配合erase 去重
__int128 , vector的unqiue 配合erase 去重
刚开始看这个题,就是简单的求逆序对 所产生的贡献,对于一个逆序对 [i , j]他们所产生的贡献是 l * (n - j)个,所以我们可以枚举j如果 j 前面有m个数大于它,那这m个数字与j所产生的贡献即为这m个数字的下标和 乘以 (n - j + 1),所以我们在用树状数组求逆序对的时候,要去维护它们的下标和
但是由于这个题的数据范围是1e9但是数字的数量只有1e6所以要进行离散化,而且答案的数据太大了
long long 也会爆,所以这时候要用__int128
代码
#include <bits/stdc++.h>
using namespace std;
typedef __int128 LL;
const int maxn = 1000000 + 5;
const int Mod = 1e9 + 7;
int n,m;
LL c[maxn];
vector <int> a,b;
int GCD(int a,int b)
{
int temp;
while(b){
temp = a % b;
a = b;
b = temp;
}
return a;
}
inline int lowbit(LL x)
{
return x&(-x);
}
void insert(LL x,LL y)
{
for(int i = x; i <= a.size(); i += lowbit(i)){
c[i] += y;
}
}
LL Query(LL x)
{
LL res = 0;
for(int i = x; i > 0; i -= lowbit(i)){
res += c[i];
}
return res ;
}
void output(LL res)
{
if(res < 10){
putchar(res + '0');
return ;
}
output(res / 10);
putchar(res % 10 + '0');
}
int main()
{
//std::ios::sync_with_stdio(false);
memset(c,0,sizeof c);
scanf("%d",&n);
for(int i = 1; i <= n; i++){
int x;
scanf("%d",&x);
a.push_back(x);
b.push_back(x);
}
//离散化
sort(a.begin(),a.end());
a.erase( unique( a.begin(),a.end() ),a.end() );
LL res = 0;
for(int i = 0; i < n; i++){
int pos = lower_bound(a.begin(),a.end(),b[i]) - a.begin() + 1;
res += 1LL * (Query(a.size()) - Query(pos)) * (n - i);
insert(pos,1 + i);
//我们可以发现当前数字与它前面数字组成的逆序对的贡献是
//它前面比他大的数字的下标和 * 乘以自己后面的下标个数。
//所以要用树状数组去维护下标和
}
output(res);
return 0;
}
京公网安备 11010502036488号