这题跟ZOJ 3606的解题思路很相似。
题意:有3中操作:1.向集合中增加一个数x(1≤x≤1e9);2.从集合中删去一个数x(保证这个数存在);3.查询集合中所有位置满足i%5==3的数a[i]的和,集合中的数按升序排列。给你一共N个操作,输出每次查询的和。
做法:因为操作只有10^5个,所以将所有查询中的数保存下来,排序之后离散化。每个数对应一个“位置”,通过标记这个“位置”是否已用来表示该数是否在集合中。
线段树节点记录两个信息:
cnt:这一段“位置”中含有多少个数,pushUp的时候cnt[rt] = cnt[ rt << 1 ] + cnt[ rt << 1 | 1 ];
sum[5]:sum[i]表示这个区间中,从左到右编号,位置模5为i的所有数的和。
pushUp的时候,sum[rt][i] = sum[lc][i], sum[rt][ (i+cnt[lc])%5 ]+= sum[rc][i]
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #define LL long long int #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define lc rt << 1 #define rc rt << 1 | 1 using namespace std; const int MAXN = 100100; struct Qry { int op; int val; } qq[MAXN]; struct node { LL sum[5]; int cnt; }; int Q; int num[MAXN]; int cnt; node Tr[ MAXN << 2 ]; void build( int l, int r, int rt ) { for ( int i = 0; i < 5; ++i ) Tr[rt].sum[i] = 0; Tr[rt].cnt = 0; if ( l == r ) return; int m = ( l + r ) >> 1; build( lson ); build( rson ); return; } void PushUp( int rt ) { Tr[rt].cnt = Tr[lc].cnt + Tr[rc].cnt; for ( int i = 0; i < 5; ++i ) Tr[rt].sum[i] = Tr[lc].sum[i]; for ( int i = 0; i < 5; ++i ) Tr[rt].sum[ (i+Tr[lc].cnt)%5 ] += Tr[rc].sum[i]; return; } void Update( int x, int op, int l, int r, int rt ) { if ( l == x && x == r ) { for ( int i = 0; i < 5; ++i ) Tr[rt].sum[i] = 0; if ( op == 1 ) { Tr[rt].cnt = 1; Tr[rt].sum[1] = num[x]; } else if ( op == 2 ) Tr[rt].cnt = 0; return; } int m = ( l + r ) >> 1; if ( x <= m ) Update( x, op, lson ); else Update( x, op, rson ); PushUp( rt ); return; } int main() { while ( scanf( "%d", &Q ) == 1 ) { cnt = 1; for ( int i = 0; i < Q; ++i ) { char tmp[8]; scanf( "%s", tmp ); if ( tmp[0] == 'a' ) { qq[i].op = 1; scanf( "%d", &qq[i].val ); num[cnt++] = qq[i].val; } else if ( tmp[0] == 'd' ) { qq[i].op = 2; scanf( "%d", &qq[i].val ); num[cnt++] = qq[i].val; } else qq[i].op = 3; } sort( num + 1, num + cnt ); cnt = unique( num + 1, num + cnt ) - num; build( 1, cnt - 1, 1 ); for ( int i = 0; i < Q; ++i ) { if ( qq[i].op == 3 ) printf( "%I64d\n", Tr[1].sum[3] ); else { int x = lower_bound( num + 1, num + cnt, qq[i].val ) - num; Update( x, qq[i].op, 1, cnt - 1, 1 ); } } } return 0; }