题意:下标模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]
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 100009
#define L(u) (u<<1)
#define R(u) (u<<1|1)
#define lint __int64
struct NODE
{
lint sum[5];
int l, r, cnt;
} node[MAXN*3];
int num[MAXN], val[MAXN], n; //num[0]记录num的个数
char oper[MAXN][5];
void build(int u, int l, int r)
{
node[u].l = l;
node[u].r = r;
node[u].cnt = 0;
for(int i = 0; i < 5; i++)
node[u].sum[i] = 0;
if(node[u].l == node[u].r) return;
int mid = (l + r) >> 1;
build(L(u), l, mid);
build(R(u), mid + 1, r);
}
void pushUp(int u)
{
node[u].cnt = node[L(u)].cnt + node[R(u)].cnt;
int x = node[L(u)].cnt;
for(int i = 0; i < 5; i++)
node[u].sum[i] = node[L(u)].sum[i];
for(int i = 0; i < 5; i++)
node[u].sum[(x+i)%5] += node[R(u)].sum[i];
}
void update(int u, int index, int flag) //flag=1表示add,flag=-1表示del
{
if(node[u].l == index && node[u].r == index)
{
node[u].cnt = 0;
for(int i = 0; i < 5; i++)
node[u].sum[i] = 0;
if(flag == 1)
{
node[u].sum[1] = num[index];
node[u].cnt = 1;
}
return;
}
int mid = (node[u].l + node[u].r) >> 1;
if(index <= mid) update(L(u), index, flag);
else update(R(u), index, flag);
pushUp(u);
}
int bfind(int l, int r, int key)
{
int mid;
while(l < r)
{
mid = (l + r) >> 1;
if(num[mid] == key) return mid;
else if(num[mid] < key) l = mid + 1;
else r = mid;
}
if(num[l] == key) return l;
return r;
}
int main()
{
while(scanf("%d", &n) != EOF)
{
int i, j;
num[0] = 0;
for(i = 1; i <= n; i++)
{
scanf("%s", oper[i]);
if(oper[i][0] != 's')
{
scanf("%d", &val[i]);
num[++num[0]] = val[i];
}
}
sort(num+1, num+1+num[0]);
for(j = 1, i = 2; i <= num[0]; i++)
if(num[j] != num[i]) num[++j] = num[i];
num[0] = j;
build(1, 1, num[0]);
for(i = 1; i <= n; i++)
{
if(oper[i][0] == 's')
printf("%I64d\n", node[1].sum[3]);
else if(oper[i][0] == 'a')
{
int index = bfind(1, num[0], val[i]);
update(1, index, 1);
}
else
{
int index = bfind(1, num[0], val[i]);
update(1, index, -1);
}
}
}
return 0;
}