洛谷 P5463 小鱼比可爱(加强版)(树状数组)

传送门


解题思路

逆序对升级版。
考虑每个逆序对对答案的贡献为多少。
假设这个逆序对的坐标为(i,j),则显然有i(n-j+1)个区间包含这个逆序对,所以对答案的贡献就是i(n-j+1)。
和以前一样用树状数组求逆序对,需要改动的地方是新加的节点不再是+1,而是+i。
估计ans最大可能在n^4左右,会炸long long,所以写个高精乘低精即可。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e6+5;
long long d[maxn],ans[50]={1};
int n,m,a[maxn],c[maxn];
inline int lowbit(int x){
	return x&(-x);
}
void add(int x,long long v){
	for(int i=x;i<=m;i+=lowbit(i)){
		d[i]+=v;
	}
}
long long query(int x){
	long long res=0;
	for(int i=x;i>=1;i-=lowbit(i)){
		res+=d[i];
	}
	return res;
}
void jia(long long x){
	ans[1]+=x;
	for(int i=1;i<ans[0];i++){
		ans[i+1]+=ans[i]/10;
		ans[i]%=10;
	}
	while(ans[ans[0]]>10){
		ans[ans[0]+1]+=ans[ans[0]]/10;
		ans[ans[0]]%=10;
		ans[0]++;
	}
}
void print(){
	for(int i=ans[0];i>=1;i--) cout<<ans[i];
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		c[i]=a[i];
	}
	sort(c+1,c+n+1);
	m=unique(c+1,c+n+1)-c-1;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(c+1,c+m+1,a[i])-c;
		jia(1ll*(n-i+1)*(query(m)-query(a[i])));
		add(a[i],i);
	}
	print();
	return 0;
}
posted @ 2021-09-16 15:35  尹昱钦  阅读(72)  评论(0编辑  收藏  举报