CF1677A

https://codeforces.com/problemset/problem/1677/A

大致题意:给定1~n的全排列,求该排列中有多少对{a,b,c,d}满足

很明显的一个思路是遍历c,再遍历a,求c~n与a+1~c-1的区间内有多少对b、d

a、c的遍历时间复杂度已经是,故b、d的统计需要O(1)解决

b和d属于两个区间,故易想到O(n)预处理前缀和,O(1)得出区间和,比较难想到的是,在遍历a或c的时候调整f

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
#include<set>
#include<queue>
#include<vector>
#include<string>
#include<map>
#include<cstdio>
#include<list>
#include<stack>
#include<unordered_set>
using namespace std;
using ll = int64_t;
ll T, n, m, k;
ll tmp, a[300005],f[5005],sum[5005];
int main()
{
T = 1;
cin >> T;
while(T--)
{
cin >> n;
ll ans = 0;
memset(f, 0, sizeof(f));
for (ll i = 1; i <= n;i++)
{
cin >> a[i];
}
for (ll i = 1; i <= n;i++)
{
for (ll j = i + 1; j <= n;j++)
{
if(a[j]<a[i])
{
f[i]++;
}
}
}
for (ll c = 1; c <= n; c++)
{
for (ll i= 1; i < c; i++)
{
if(a[i]>a[c])
{
f[i]--;//更新f[i]
}
}
sum[0] = 0;
for (ll i = 1; i < c;i++)
{
sum[i] = sum[i - 1] + f[i];
}
for (ll i = 1; i < c;i++)//枚举a
{
if(a[i]<a[c])
{
ans += sum[c - 1] - sum[i];//剔除1~a的部分
}
}
}
cout << ans << "\n";
}
return 0;
}

其中,a分割出的区间暂时不需要,故用前缀和,而c分割出的区间永远不需要,故直接更新f