Codeforces 1000F
题意
给定1个长度为\(n\)的静态序列,\(q\)次询问\([l_i,r_i]\)内恰好出现1次的数(输出任意1个即可);若不存在仅出现1次的数,则输出0。\(1 \leq a_i,n,q\leq 5 \times10^5\)
题解
首先考虑求解区间内仅出现1次的数的个数。
有1种不错的思路是,既然仅出现1次的元素才能计入答案,则不妨令各类元素的第1个贡献为1,第2个贡献为-1,其余不贡献,则区间和即为恰好出现1次的元素种数。(这种思路的本质是通过拆分/后悔操作解决区间限制问题,差分也是同理)。
但对于多组询问,元素的贡献也是动态的;考虑有序地处理:仅\(l_i\)会影响各位置的贡献,故将询问按\(l_i\)从小到大排序,则每次\(l_i\)移动时只需修改同类元素向后两位的贡献。单点修改,区间求和,基于位置的线段树即可维护。
再考虑求出任意1个\([l_i,r_i]\)内恰好出现1次的数。
如果延续上文的思路,则应查找出1类在\([l_i,r_i]\)中出现\(1\)的贡献且未出现\(-1\)的贡献的数。
这看上去需要建立基于权值的线段树,但这又无法解决位置限制的问题。与上文矛盾。
考虑维护另外1些基于位置的信息。按照“位置”的表达方式转换限制,即查找出1个位置\(pos\),使\(a[pos]\)在\([l_i,n]\)中第1次出现,且\(next[pos](即后1个同类元素的位置)> r_i\)。
故在基于位置的线段树上维护\(next\)及其最大值\(nextmax\),即可通过线段树的区间查询,在\(logn\)的时间内求解任意1个\(next > r_i\)的位置。
顺便地,本题实际询问是否存在符合条件的数(而不是个数),判断\(nextmax\)是否大于\(r_i\)即可。
时间复杂度\(O(nlogn)\)。[代码见此](https://github.com/littlewyy/OI/blob/master/cf 1000f segment tree)
回顾与思考
拆分操作;离线有序处理;主动维护其它信息。
另解
莫队?跑去开坑了。