题目链接:https://codeforces.com/contest/1677/problem/A
描述
Tokitsukaze has a permutation p of length n. Recall that a permutation p of length n is a sequence p1,p2,…,pn consisting of n distinct integers, each of which from 1 to n (1≤pi≤n).
She wants to know how many different indices tuples [a,b,c,d] (1≤a<b<c<d≤n) in this permutation satisfy the following two inequalities:
pa < pc and pb > pd.
Note that two tuples [a1,b1,c1,d1] and [a2,b2,c2,d2] are considered to be different if a1≠a2 or b1≠b2 or c1≠c2 or d1≠d2.
输入
The first line contains one integer t (1≤t≤1000) — the number of test cases. Each test case consists of two lines.
The first line contains a single integer n (4≤n≤5000) — the length of permutation p.
The second line contains n integers p1,p2,…,pn (1≤pi≤n) — the permutation p.
It is guaranteed that the sum of n over all test cases does not exceed 5000.
输出
For each test case, print a single integer — the number of different [a,b,c,d] tuples.
思路:
PS:好久没写了感觉有点生疏了。
题目的大致意思是给定一个有n个不同的数构成的数组P,1<=Pi<=n,求满足Pa<Pc,Pb>Pd且a<b<c<d的四元组有多少。当时思路是先确定a和c的位置,然后计算b与d的对数。a与c确定后,对于一个b来说能与它配对的d的个数为大于c中Pd<Pb的个数。为了加快计算速度,可以用树状数组分别去维护c+1至n存在的数与a+1至c-1存在的数。以先第一重循环枚举a第二重循环枚举c为例,枚举c后(b,d)的对数为{c-1时的对数}减去{a+1至c-2中大于Pc的数}加上{c+1至n中小于Pc-1的数},若此时满足Pa<Pc则加上此时满足条件(b,d)的对数。
dp[a][c] = dp[a][c-1] + cnt(c+1,n,P[c-1]) - ( cnt(a+1,c-2,n) - cnt(a+1,c-2,P[c]) )
dp[a][c]为a与c确定后符合条件的(b,d)对数
a+1<c,dp[a][a+1]=0;
cnt(l,r,x)为求数组[l,r]中小于等于x的个数。
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
const int Ms=5005;
int T[2][Ms];
int a[Ms];
int lowbit(int x)
{
return x&(-x);
}
void update(int no,int key,int x)
{
while(key<=Ms)
{
T[no][key]+=x;
key+=lowbit(key);
}
}
int getsum(int no,int key)
{
int sum=0;
while(key>0)
{
sum+=T[no][key];
key-=lowbit(key);
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
long long ans=0,tmp=0;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
for(int i=1;i<=n-3;i++)
{
memset(T,0,sizeof T);
for(int p=i+3;p<=n;p++)update(1,a[p],1);
tmp=0;
for(int j=i+2;j+1<=n;j++)
{
update(0,a[j-1],1);
tmp+=getsum(1,a[j-1]);
if(a[i]<a[j])
{
ans+=tmp;
}
tmp-=getsum(0,n)-getsum(0,a[j+1]);
update(1,a[j+1],-1);
}
}
printf("%lld\n",ans);
}
return 0;
}
若有什么错误,欢迎指正^ _ ^ 。