HDU 4288 Coder ( 离散化 + 离线 + 线段树 )

时间:2022-11-07 00:08:03

这题跟ZOJ 3606的解题思路很相似。

题意:有3中操作:1.向集合中增加一个数x(1≤x≤1HDU 4288 Coder ( 离散化 + 离线 + 线段树 )e9);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 = ; struct Qry
{
int op;
int val;
} qq[MAXN]; struct node
{
LL sum[];
int cnt;
}; int Q;
int num[MAXN];
int cnt;
node Tr[ MAXN << ]; void build( int l, int r, int rt )
{
for ( int i = ; i < ; ++i ) Tr[rt].sum[i] = ;
Tr[rt].cnt = ; if ( l == r ) return;
int m = ( l + r ) >> ;
build( lson );
build( rson );
return;
} void PushUp( int rt )
{
Tr[rt].cnt = Tr[lc].cnt + Tr[rc].cnt;
for ( int i = ; i < ; ++i ) Tr[rt].sum[i] = Tr[lc].sum[i];
for ( int i = ; i < ; ++i ) Tr[rt].sum[ (i+Tr[lc].cnt)% ] += 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 = ; i < ; ++i ) Tr[rt].sum[i] = ;
if ( op == )
{
Tr[rt].cnt = ;
Tr[rt].sum[] = num[x];
}
else if ( op == ) Tr[rt].cnt = ;
return;
}
int m = ( l + r ) >> ;
if ( x <= m ) Update( x, op, lson );
else Update( x, op, rson );
PushUp( rt );
return;
} int main()
{
while ( scanf( "%d", &Q ) == )
{
cnt = ;
for ( int i = ; i < Q; ++i )
{
char tmp[];
scanf( "%s", tmp );
if ( tmp[] == 'a' )
{
qq[i].op = ;
scanf( "%d", &qq[i].val );
num[cnt++] = qq[i].val;
}
else if ( tmp[] == 'd' )
{
qq[i].op = ;
scanf( "%d", &qq[i].val );
num[cnt++] = qq[i].val;
}
else qq[i].op = ;
} sort( num + , num + cnt );
cnt = unique( num + , num + cnt ) - num;
build( , cnt - , ); for ( int i = ; i < Q; ++i )
{
if ( qq[i].op == )
printf( "%I64d\n", Tr[].sum[] );
else
{
int x = lower_bound( num + , num + cnt, qq[i].val ) - num;
Update( x, qq[i].op, , cnt - , );
}
}
}
return ;
}