题意:
给定一个 \(N\),求所有 \(N\) 的子区间 \([l,r],1\leq l\leq r\leq N\) 中满足 \(i \in [l,r]\) 中有至少一个 \(A_i\) 的出现次数有且仅出现一次。
题意很明确,如何解决?
暴力:
直接 \(N^2\) 扫一遍然后进行每个区间的特判即可,复杂度 \(O(N^3)\) 估计只能过样例。
莫队:
由于发现对于一个区间 \([l,r]\) 只要其中一个 \(i \in [l,r]\) 中的 \(count(A_i)\) 仅仅出现一次且拓展的 \([l,r]\) 如果不等于 \(A_i\) 那么这个拓展的区间也是合法的区间。故可以用莫队做,但是可能会很麻烦。具体的:
inline void upd(int x){
mp[a[x]]--;
}
inline bool que(int x){
if(mp[a[x]]>=1){
return false;
}
return true;
}
这样做是 \(O(N^2\sqrt N)\) 的反正也过不了。
正解:
考虑用 \(L_i\) 表示 \(i\) 最左出现的位置, \(R_i\) 表示 \(i\) 最右边出现的位置,那么对于一个 \(i\) 肯定满足 \([L_{A_i},i]\) 满足和 \([i,R_{A_i}]\) 满足,并且 \([L_{A_i}-1,.....k<R]\) 都满足,同理右端点也一样,所以由乘法原理得所有满足的区间个数有 \((R_i-i+1)(i-L_i+1)\) 个。
但是这样做会发现有很多数会重复计算,所有可以用扫描线算法来计算重合的部分,(只不过是一维的)也可以用线段树的区间赋值,于是答案即为总和-重合部分的面积,复杂度为 \(O(N\log_2 N)\) 可以过的。