利用树状数组离线 统计一个区间内不同数字的个数
基本思路是树状数组, 但是有重复的数, 要保证在一个区间内只更新过一次
所做的处理是用先遍历记录数字的数组a, 用数-位置数组 mp[a[i]] 来记录每个数第一次出现的位置并该点更新
这个操作对应的代码
1 for(int i = 1; i <= n; i++) { 2 if(mp[a[i]] == 0) { //如果是第一次出现, 记录第一次出现位置并更新 3 Add(i, 1); 4 mp[a[i]] = i; 5 } 6 }
记录左右查询, 每个查询按区间右端点R[i]从小到大排序
设一个扫描线k, 它的目的保证R[i]之前所有不同的点只更新过一次, 并且是在离R[i]最近的那个点更新
如此便可以写出这样一段代码
1 for(int i = 1; i <= query_num; i++) { 2 while(k <= R[i]) { 3 if(mp[a[i]] != k) { //如果不是最新次出现 4 Add(mp[a[k]], -1); //将上一次出现的更新-1 5 Add(k, 1); //将这个位置新出现的更新1 6 mp[a[k]] = k; //更新这个数最近一次的位置 7 } 8 k++; 9 } 10 ans[i] = Sum(ed[i]) - Sum(st[i] - 1); 11 }