CF 85D Sum of Medians (五颗线段树)

http://codeforces.com/problemset/problem/85/D

题意:

给你N(0<N<1e5)次操作,每次操作有3种方式,

1.向集合里加一个数a(0<a<1e9)(增加数a之前的集合一定不存在a)

2.向集合里删一个数a(0<a<1e9)(删除数a之前的集合一定存在a)

3.将下标i%5==3的数相加,计算总和并相加.

分析:

先离散,然后线段树,sum[i]用来标识前i项有几个数,ans[rt][i]表示以rt为根的子树中第i大数的和

// File Name: d.cpp
// Author: Zlbing
// Created Time: 2013/7/18 20:22:40

#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define CL(x,v); memset(x,v,sizeof(x));
#define INF 0x3f3f3f3f
#define LL long long
#define REP(i,r,n) for(int i=r;i<=n;i++)
#define RREP(i,n,r) for(int i=n;i>=r;i--)

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN=1e5+1000;
char str[MAXN][10];
int d[MAXN];
int hash[MAXN];
int tot;

int sum[MAXN<<2];
LL ans[MAXN<<2][10];
int flag;

void pushup(int rt)
{
    for(int i=0;i<5;i++)
    {
        ans[rt][i]=ans[rt<<1][i]+ans[rt<<1|1][(i-sum[rt<<1]%5+5)%5];
    }
}
void update(int pos,int l,int r,int rt)
{
    sum[rt]+=flag*2-1;
    if(l==r)
    {
        ans[rt][0]=hash[pos]*flag;
        return;
    }
    int m=(l+r)>>1;
    if(pos<=m)update(pos,lson);
    else update(pos,rson);
    pushup(rt);
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        tot=0;
        REP(i,1,n)
        {
            scanf("%s",str[i]);
            if(str[i][0]=='a'||str[i][0]=='d')
            {
                scanf("%d",&d[i]);
                hash[tot++]=d[i];
            }
        }
        sort(hash,hash+tot);
        tot=unique(hash,hash+tot)-hash;
        CL(ans,0);
        CL(sum,0);
        REP(i,1,n)
        {
            if(str[i][0]=='a')
            {
                flag=1;
                int pos=lower_bound(hash,hash+tot,d[i])-hash;
                update(pos,1,tot,1);
            }
            else if(str[i][0]=='d')
            {
                flag=0;
                int pos=lower_bound(hash,hash+tot,d[i])-hash;
                update(pos,1,tot,1);
            }
            else {
                printf("%I64d\n",ans[1][2]);
            }
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/arbitrary/p/3199322.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值