头疼,无心学习,做一题舒爽一下身心
题意:给1-n n个数的随机排列,求满足( 1≤a<b<c<d≤n 2. Aa<Ab 3. Ac<Ad )数列的个数
分析:1.发现好似树状数组的题,并且有序对Aa Ab 和 有序对Ac Ad貌似可以分开来思考
2.对于满足条件的有序对Aa,Ab的个数,Aa只需要保存Aa的个数,那也就是1,可以直接用树状数组来求
3.那对于有序对Ac和Ad呢,不仅仅要求出Ac,Ad的个数,还要与有序对Aa,Ab产生联系
4.枚举Ac,并且Ac保存Ac之前序列有序对Aa,Ab的个数。
5.所以可以在求每一个有序对Ac,Ad的同时求出Ac之前序列有序对Aa,Ab的个数
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long LL;
#define MAXN 50010
#define lowbit(i) ((i) & (-i))
LL pre2[MAXN],pre1[MAXN];
int arr[MAXN];
inline LL sum(int i,LL * cur)
{
LL ans = 0;
for(;i;i -= lowbit(i))
ans += cur[i];
return ans;
}
inline void modify(int i,int maxn,LL key,LL * cur)
{
for(;i <= maxn;i += lowbit(i))
cur[i] += key;
}
int main()
{
int _,n;
scanf("%d",&_);
while(_--)
{
scanf("%d",&n);
for(int i = 0;i < n;i++)
scanf("%d",&arr[i]);
memset(pre1,0,8 * n + 20);
memset(pre2,0,8 * n + 20);
LL prefix = 0,ans = 0;
for(int i = 0;i < n;i++)
{
modify(arr[i],n,prefix,pre2);
prefix += sum(arr[i],pre1);
modify(arr[i],n,1,pre1);
ans += sum(arr[i] - 1,pre2);
}
printf("%I64d\n",ans);
}
}