hdu 4288 线段树+离散化

因为值的范围较大,所以要进行去重后离散化,用线段树维护一组和即可,就是模为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] ); 
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值