求数列 $\{a_n\}$ 所有子区间不同数个数的和。
套路题,令 $nxt_i$ 表示 $a_i$ 下一个和 $a_i$ 相同的位置。
对于一个 $R$ ,如果 $1\le i\le R$ 中 $nxt_i>R$ ,就说明 $a_i$ 是 $[1,R]$ 中最后一个 $a_i$ ,只要 $L\in[1,i]$ 那么 $a_i$ 都可以产生贡献,按顺序枚举 $R$ ,求 $\sum_{nxt_i>R}i$ 就好了。
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxn=100000;
int n,a[maxn+5],nxt[maxn+5],lst[maxn+5];LL c[maxn+5],ans;
void Insert(int x,int y) {for (int i=x;i<=n+1;i+=i&-i) c[i]+=y;}
LL Sum(int x) {LL sum=0;for (int i=x;i;i-=i&-i) sum+=c[i];return sum;}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
for (int i=1;i<=n;i++) lst[i]=n+1;
for (int i=n;i;i--) nxt[i]=lst[a[i]],lst[a[i]]=i;
for (int i=1;i<=n;i++){
Insert(n+1-nxt[i]+1,i);
ans+=Sum(n+1-(i+1)+1);
}
printf("%lld\n",ans);return 0;
}