题目大意
给了 n(1≤n≤100000 个操作,每个操作要么是在集合中添加一个整数(在区间 [1, 109] 中,且保证不在集合中),要么是删除一个整数(保证在集合中),还有一个操作 sum,询问的是当前集合中,所有元素从小到大排列好之后,下标除以 5 余数为 3 的所有数的和
做法分析
先把所有的操作存储下来,然后把每一个出现过的整数(添加的和删除的)全部“有序的”离散化,这样,我们再添加或者删除的时候就找得到具体的位置了,接着就是怎么用线段树做的问题了:
可以这样,线段树的每个节点存一个数组 sum[5],表示当前节点覆盖的区间中,从左到有编号,模 5 为 0,1,2,3,4的所有数的和
每个节点再保存一个当前节点所包含的区间中有多少个数的信息:cnt。那么:
添加的时候就是在相应的位置把整数加进去,并把 cnt+1
删除的时候就是在相应的位置赋值为 0,并把 cnt-1
关于 pushUp 的问题,我们可以这样考虑:
父亲的 cnt 肯定是两个儿子的 cnt 的和
父亲的 sum 肯定赋初值为 左儿子 的 sum
右儿子的 sum[i] 对应的是父亲的 sum[(i+Lson.cnt)%5],以此作为更新的依据
每一个求和的询问,直接输出根节点的 sum[3] 就行
参考代码
HDU 4288 ::iterator it=haha.begin(); it!=haha.end(); it++)88 if(ihash.find(*it)==ihash.end())89 ihash.insert(make_pair(*it, ++len));90 tree.build(1, 1, len);91 for(int i=0; i
1 #include2 #include 3 #include 4 #include 5 #include 6 #include