[ABC318E] Sandwiches 题解
一开始考虑枚举 \(i\) 或 \(k\) 来统计,发现需要 \(O(n^2)\) 的时间复杂度。
因此考虑枚举 \(j\),我们可以用 \(l_x\) 表示满足 \(i<j,a_i=x\) 的数量,用 \(r_x\) 表示满足 \(j<k,a_k=x\) 的数量。
那么会发现对于每一个 \(j\),它的贡献应为 \(\sum_{x=1,x \not = a_j}^n l_xr_x\),注意到 \(a_j\) 只有一项,所以考虑容斥,将这一项单独提出来,那么贡献就变成了 \((\sum_{x=1}^n l_xr_x)-l_{a_j}r_{a_j}\),因此我们可以先处理出 \(\sum_{x=1}^n l_xr_x\),在每次 \(j\) 移动的时候修改贡献即可。预处理时间复杂度 \(O(n)\),修改为 \(O(1)\),每次统计答案为 \(O(1)\),总时间复杂度 \(O(n)\),足以通过本题。
#include <cstdio>
const int N=3e5+5;
int n;
int a[N];
int l[N],r[N];
long long ans,sum;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
if(i==1) l[a[i]]++;//初始化l和r
else if(i!=2) r[a[i]]++;
}
for(int i=1;i<=n;i++) sum+=(1ll*l[i]*r[i]);//预处理
for(int j=2;j<n;j++) {
ans+=(sum-1ll*l[a[j]]*r[a[j]]);//统计答案
++l[a[j]];sum+=r[a[j]];//修改
--r[a[j+1]];sum-=l[a[j+1]];
}
printf("%lld\n",ans);
return 0;
}

浙公网安备 33010602011771号