题解 UVA1428 【Ping pong】
题目链接:Link
Solution
令 \(x_i\) 表示从 \(a_1\) 到 \(a_{i-1}\) 中比 \(a_i\) 小的数的个数, \(y_i\) 表示从 \(a_{i+1}\) 到 \(a_n\) 中比 \(a_i\) 小的数的个数,则答案等于 $\sum_{k=1}^N x[i](n-i-y[i])+(i-x[i]-1)y[i] $
可以用树状数组动态维护。
贴代码:
#include<cstdio>
#include<cstring>
const int maxn=100005;
int T,n,r;
int a[maxn],b[maxn];
int lowbit(int x) { return x&-x; }
inline int sum(int x)
{
int res=0;
while(x>0)
{
res=res+b[x];
x-=lowbit(x);
}
return res;
}
inline void add(int x,int d)
{
a[x]=a[x]+d;
while(x<=r)
{
b[x]=b[x]+d;
x+=lowbit(x);
}
}
inline void set(int x,int d) { add(x,d-a[x]); }
int v[maxn],x[maxn],y[maxn];
long long res;
int main()
{
#ifdef local
freopen("pro.in","r",stdin);
#endif
scanf("%d",&T);
while(T-->0)
{
scanf("%d",&n);
r=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&v[i]);
if(v[i]>r) r=v[i];
}
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=1;i<=n;i++)
{
set(v[i],1);
x[i]=sum(v[i]-1);
}
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=n;i>=1;i--)
{
set(v[i],1);
y[i]=sum(v[i]-1);
}
res=0;
for(int i=2;i<=n-1;i++) res=res//小心溢出!
+(long long)x[i]*(n-i-y[i])
+(long long)(i-x[i]-1)*y[i];
printf("%lld\n",res);
}
return 0;
}
本作品由happyZYM采用知识共享 署名-非商业性使用-相同方式共享 4.0 (CC BY-NC-SA 4.0) 国际许可协议(镜像(简单版)镜像(完整版))进行许可。
转载请注明出处:https://www.cnblogs.com/happyZYM/p/11379985.html (近乎)全文转载而非引用的请在文首添加出处链接。