E题:Sandwiches
标签:数学、思维
题意:给你一个长度为
N
N
N 的正整数序列:
A
=
(
A
1
,
A
2
,
…
,
A
N
)
A=(A_1,A_2,…,A_N)
A=(A1,A2,…,AN),求满足下列所有条件的正整数三元组
(
i
,
j
,
k
)
(i,j,k)
(i,j,k) 的个数:
- $ 1≤i<j<k≤N$
- $ A_i=A_k$
- $ A_i \neq A_j$
题解:这道题本质其实就是:求相等的数之间夹的不同的数的个数。举几个例子,我们来找找规律:
设
k
k
k为非
11
11
11的数
11
11
11
a
a
a个
k
k
k
11
11
11 => 符合要求的有
a
a
a个
11
11
11
a
a
a个
k
k
k
11
11
11
b
b
b个
k
k
k
11
11
11 => 符合要求的有
2
a
+
2
b
2a+2b
2a+2b个
11
11
11
a
a
a个
k
k
k
11
11
11
b
b
b个
k
k
k
11
11
11
c
c
c个
k
k
k
11
11
11 => 符合要求的有
3
a
+
4
b
+
3
c
3a+4b+3c
3a+4b+3c个
依次类推如果夹了
a
、
b
、
c
、
d
a、b、c、d
a、b、c、d,=>
4
a
+
6
b
+
6
c
+
4
d
4a+6b+6c+4d
4a+6b+6c+4d个
在图上可以画一画,每个
11
11
11会和对应的其他
11
11
11,组成的区间,然后去统计一下每块相邻区间的计算次数,能得到式子:
k
∗
(
l
e
n
−
k
)
k*(len-k)
k∗(len−k)。
实际的算法流程就先把对应数值的下标塞到一个不定长数组里面,然后求一下相邻的相同的数,每一块区间能够产生的贡献,累加一下就可以了。
代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
typedef long long ll;
vector<ll> a[N];
int main() {
ll n, x, ans = 0;
cin >> n;
for (ll i = 1; i <= n; i++) {
cin >> x;
a[x].push_back(i);
}
for (ll i = 1; i <= n; i++) {
ll len = a[i].size();
for (ll k = 1; k < len; k++) {
ans += k * (len - k) * (a[i][k] - a[i][k-1] - 1);
}
}
cout << ans << endl;
return 0;
}