链接
http://codeforces.com/contest/85
题意
共n个操作,有3种类型
- add x
向集合中添加数x - del x
将集合中数x删除 - sum
将集合中所有数进行从小到大排序,求出所有数下标对5取余为3的数的和即 ∑ i n a [ i ] ( 其 中 i % 5 = = 3 ) \sum_i^na[i] (其中i\%5==3) ∑ina[i](其中i%5==3)
分析
这里使用线段树,首先考虑x为1e9,所以对输入的x进行统计,然后离散化,对离散化后的x进行建立一个线段树,显然线段树的每个节点[l,r]需要存储区间[l,r]的下标对5取余为3的数的和,那么必然存在子区间的合并,
这时又有这样一个问题,对于[l1,r1],[l2,r2](l2-2==r1)合并之后区间[l,r]的下标对5取余为3的数的和,来自左子区间[l1,r1]下标对5取余为3的数的和,再加上右子区间的和,但是合并之后是有问题产生的,左子区间下标对5取余为3的数是不变的,对于右子区间来说,对5取余为(0、1、2、3、4)的数都可能成为合并之后下标对5取余为3的数的和,它是与左子区间的个数有关的;假如左子区间个数为8,那么对于右子区间来说,原来它的下标mod5为1的数合并之后,即产生对mod5为3的贡献(模拟一下),所以对于每个节点,我们都需要它的对5取余的所有情况的和(余数为0、1、2、3、4的和),所以需要定义一个mod数组,mod[x]代表余数为x的数的和,并且最关键的是区间的合并;
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;
#define inf 0x7f7f7f7f
#define maxn 1000005
#define N 200005
#define P 2
typedef long long ll;
int n, k, a[maxn], cnt;
string s[maxn];
int val[maxn];
struct Tree {
ll cnt, mod[5];
} tree[4 * maxn];
void push_up(int x) {
for (int i = 0; i < 5; i++)
tree[x].mod[i] = tree[x << 1].mod[i] + tree[x << 1 | 1].mod[((i - tree[x << 1].cnt) % 5 + 5) % 5];
}
void build(int x, int l, int r) {
tree[x].cnt = 0;
if (l == r) {
memset(tree[x].mod, 0, sizeof(tree[x].mod));
return;
}
int mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
push_up(x);
}
void update(int l, int r, int x, int pos, int val) {
tree[x].cnt += val;
if (l == r) {
if (tree[x].cnt == 0)
tree[x].mod[1] = 0;
else tree[x].mod[1] = a[pos];
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)update(l, mid, x << 1, pos, val);
else update(mid + 1, r, x << 1 | 1, pos, val);
push_up(x);
}
int main() {
while (scanf("%d", &n) != EOF) {
for (int i = 1; i <= n; i++) {
cin >> s[i];
if (s[i] != "sum") {
scanf("%d",&val[i]);
a[++cnt] = val[i];
}
}
sort(a + 1, a + 1 + cnt);
int len = unique(a + 1, a + 1 + cnt) - a - 1;
if(len == 0)len = 1;
build(1, 1, len);
for (int i = 1; i <= n; i++) {
string ty = s[i];
if (ty == "add") {
int pos = lower_bound(a + 1, a + 1 + len, val[i]) - a;
update(1, len, 1, pos, 1);
} else if (ty == "del") {
int pos = lower_bound(a + 1, a + 1 + len, val[i]) - a;
update(1, len, 1, pos, -1);
} else cout << tree[1].mod[3] << endl;
}
}
}