您的位置:首页 > 其它

UVA 1428 Ping Pong(树状数组)

2016-10-21 08:08 441 查看
取low=min(a[i]|1<=i<=n},up=max(a[i]|1<=i<=n},那么区间就是{low, up},那么只要统计出当前a[i]左边有多少比他小的,右边有多少比他小的即可,因为给出的序列是有顺序的,所以在加入需要加入一个统计一个,如果先全部加入了,那么则会导致统计结果变大。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define ret(i,a,b) for(int i=(a);i>=(b);i--)
#define ss(x) scanf("%d",&x)
const int maxn=100000+5;
int a[maxn],C[maxn],c[maxn],d[maxn];
int n,up;
int lowbit(int x) {return x&(-x);}
void add(int x,int d)
{
while(x<=up){
C[x]+=d;x+=lowbit(x);
}
}
int sum(int x)
{
int ret=0;
while(x){
ret+=C[x];x-=lowbit(x);
}
return ret;
}
int main()
{
int t;
ss(t);
while(t--)
{
up=0;
memset(a,0,sizeof(a));
memset(C,0,sizeof(C));
ss(n);
rep(i,1,n) {ss(a[i]);up=max(up,a[i]);}
rep(i,1,n) {add(a[i],1);c[i]=sum(a[i]-1);}
memset(C,0,sizeof(C));
ret(i,n,1) {add(a[i],1);d[i]=sum(a[i]-1);}
long long ans=0;
rep(i,1,n) ans+=c[i]*(n-i-d[i])+(i-1-c[i])*d[i];
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: