因为值的范围较大,所以要进行去重后离散化,用线段树维护一组和即可,就是模为0-4的和,
利用dp的思想可知,sum[i] =左子树的sum[i]+右子树的sum[ (5+i-左子树的点的个数%5)%5],
那么只要用线段树维护这个和就可以了
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#define MAX 100007
using namespace std;
typedef long long LL;
struct Node
{
int l,r,cnt;
LL sum[7];
}tree[MAX<<2];
struct Point
{
int id;
LL v;
bool operator < ( const Point & a ) const
{
return v < a.v;
}
}p[MAX];
void build ( int u , int l , int r )
{
tree[u].l = l , tree[u].r = r;
memset ( tree[u].sum , 0 , sizeof ( tree[u].sum ) );
tree[u].cnt = 0;
if ( l == r ) return;
LL mid = l + r >> 1;
build ( u<<1 , l , mid );
build ( u<<1|1 , mid+1 , r );
}
void push_up ( int u )
{
for ( int i = 0 ; i < 5 ; i++ )
tree[u].sum[i] = tree[u<<1].sum[i]
+ tree[u<<1|1].sum[(5+(i-tree[u<<1].cnt)%5)%5];
tree[u].cnt = tree[u<<1].cnt + tree[u<<1|1].cnt;
}
void add ( int u , int x , LL v )
{
int l = tree[u].l , r = tree[u].r;
if ( l == r )
{
tree[u].sum[1] = v;
tree[u].cnt = 1;
return;
}
int mid = l + r >> 1;
if ( x > mid ) add ( u<<1|1 , x , v );
else add ( u<<1 , x , v );
push_up ( u );
}
void del ( int u , int x )
{
LL l = tree[u].l , r = tree[u].r;
if ( l == r )
{
tree[u].sum[1] = 0;
tree[u].cnt = 0;
return;
}
LL mid = l + r >> 1;
if ( x > mid ) del ( u<<1|1 , x );
else del ( u<<1 , x );
push_up ( u );
}
int n;
char s[MAX][15];
LL a[MAX];
int b[MAX];
int main ( )
{
while ( ~scanf ( "%d" , &n ) )
{
int cnt = 0;
int num = 0;
for ( int i = 0 ; i < n ; i++ )
{
scanf ( "%s" , s[i] );
if ( s[i][0] != 's' )
{
scanf ( "%lld" , &a[i] );
p[cnt].v = a[i],
p[cnt].id = i,
cnt++;
}
}
sort ( p , p + cnt );
b[p[0].id] = ++num;
for ( int i = 1 ; i < cnt ; i++ )
{
if ( p[i].v == p[i-1].v ) b[p[i].id] = num;
else b[p[i].id] = ++num;
}
build ( 1 , 1 , num+1 );
for ( int i = 0 ; i < n ; i++ )
{
if ( s[i][0] == 's' )
printf ( "%lld\n" , tree[1].sum[3] );
else if ( s[i][0] == 'a' )
add ( 1 , b[i] , a[i] );
else del ( 1 , b[i] );
}
}
}