AcWing 241. 楼兰图腾
原题链接
简单
作者:
xiaoqi_
,
2021-03-08 10:42:20
,
所有人可见
,
阅读 297
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=200010;
int n;
int a[N];
int tr[N];
int Greater[N],lower[N];
int lowbit(int x)
{
return x&-x;
}
//在x的位置加上c
void add(int x,int c)
{
//
for(int i=x;i<=n;i+=lowbit(i)) tr[i]+=c;
}
//查询前x个数的和
int sum(int x)
{
//求tr[1]~tr[x]的数的和,即1~x的和,这里tr数组的值是0或1,表示是否出现过,所以这个sum是用来求1~x中出现的数的个数
int res=0;
for(int i=x;i;i-=lowbit(i)) res+=tr[i];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
//预处理树状数组
for(int i=1;i<=n;i++)
{
int y=a[i]; //第i个数
//和前缀和相似
Greater[i]=sum(n)-sum(y); //求[y+1,n]区间内数的次数
lower[i]=sum(y-1); //求[1,y-1] 区间内数的次数
add(y,1); //将这个y点加入到树状数组中
}
memset(tr,0,sizeof tr);
LL res1=0,res2=0;
for(int i=n;i;i--)
{
int y=a[i];
res1+=Greater[i]*(LL)(sum(n)-sum(y));//V
res2+=lower[i]*(LL)(sum(y-1));//^
add(y,1);
}
printf("%lld %lld\n",res1,res2);
return 0;
}