auto add = [] (int x) { if (++ cnt[x] == 1) cur ++; }; for (int i = 1; i <= n; i ++) { memset(cnt, 0, sizeof cnt), cur = 0; for (int j = i; j <= n; j ++) add(a[j]), ans += cur; } cout << ans << '\n';
不难发现,如果区间中没有重复的数,那么贡献就是区间的长度,如果存在相同的数,那么这个数的贡献仍旧为 1,为了方便处理,我们钦定每个区间出现第一次的数存在贡献,定义数组 g,其中 gi 表示第 i 个数在这 n2 个区间中所作出的总贡献,答案即为 ∑i=1ngi。
那么如何求出每个元素作为区间第一个数出现的总贡献呢?先抛开这个问题不谈,思考每个下标在 n2 个区间中出现的次数,通过对左边界 l 进行讨论,不难发现,对于第 i 个数,它前面有 i−1 个数,而这些数作为左边界时,右边界可以取 i,i+1,i+2,…,n 一共 n−i+1 种取值,当 l=i 时,同样也有 n−i+1 种 (这不是废话么)。因此对在数组中第一次出现的数,它所做出的贡献为 i×(n−i+1)。
signedmain()// 记得开 long long { cin >> n; for (int i = 1; i <= n; i ++) cin >> a[i]; for (int i = 1; i <= n; i ++) L[i] = cur[a[i]], cur[a[i]] = i; for (int i = 1; i <= n; i ++) ans += (i - L[i]) * (n - i + 1); cout << ans << '\n'; return0; }