Problem - 1677A - Codeforces
时津风有一个长度为n的排列组合p。回顾一下,长度为n的排列组合p是由n个不同的整数组成的序列p1,p2,...,pn,每个整数从1到n(1≤pi≤n)。
她想知道在这个排列组合中,有多少个不同的指数图组[a,b,c,d](1≤a<b<c<d≤n)满足以下两个不等式。
pa<pc和pb>pd。
请注意,如果a1≠a2或b1≠b2或c1≠c2或d1≠d2,两个图元[a1,b1,c1,d1]被认为是不同的。
输入
第一行包含一个整数t(1≤t≤1000)--测试案例的数量。每个测试用例由两行组成。
第一行包含一个整数n(4≤n≤5000)--包络的长度p。
第二行包含n个整数p1,p2,...,pn(1≤pi≤n)--包络p。
保证所有测试案例的n之和不超过5000。
输出
对于每个测试案例,打印一个整数--不同的[a,b,c,d]图组的数量。
例子
输入复制
3
6
5 3 6 1 4 2
4
1 2 3 4
10
5 1 6 2 8 3 4 10 9 7
输出拷贝
3
0
28
注意
在第一个测试案例中,有3个不同的[a,b,c,d]图组。
p1=5, p2=3, p3=6, p4=1,其中p1<p3,p2>p4满足不等式,所以[a,b,c,d]图组中的一个是[1,2,3,4]。
同样地,另外两个图元是[1,2,3,6],[2,3,5,6]。
题解:
我们可以枚举b,过程中,利用桶排的思想把对b前面的数标记,利用前缀和,找到,b后面的数c有多少个是大于a的res,然后在内部循环,c后面的数,找到大于当前b的加上,然后更新res,因为b后面的数可以成为d,也可以为c
(说的有点乱,具体代码有体现)
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define int long long
//1 1 3 3 3
int n,ans;
int a[200050];
int tong[5005];
int d[5005];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
cin >> a[i],tong[i] = 0;
int ans = 0,res;
for(int i = 2;i < n-1;i++)(枚举b的位置)
{
tong[a[i-1]]++;(对a的位置进行桶排标记)
for(int j = 1;j <= n;j++)
{
d[j] = d[j-1] + tong[j];(统计每个位置大于前面的有几个数)
}
res = d[a[i+1]];//得到c大于a的个数
for(int j = i+2;j <= n; j++)//枚举d
{
if(a[i] > a[j])//如果b > d
{
ans += res;
}
res += d[a[j]];//更新res如果a[j]前面有数,说明这个数也可以a[j]也可以为c
}
}
cout<<ans<<"\n";
}
signed main()
{
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}
//2 5
//3
//9 7
//2 3 4 3
//1 2 3 4 5
// 3