CF 85D Sum of Medians

题目链接:http://www.codeforces.com/problemset/problem/85/D

题目大意:求集合{a1,a2,a3,....}且a1<a2<a3...求,元素不是按从小到大添加到集合中的,且还有移除元素的操作,询问是多次的.

思路:看到这种边更新边询问,不经意的想到线段树.
用线段树维护mod5=3的sum3,直接求是不现实的,我们可以把集合(这边的集合是指全部出现过的元素所构成的集合,且元素在集合中升序排列)按照线段树来分成若干子集,这样重点就在于子集合并.
容易知道合并时对于左子集来说sum3不会变化,但是右子集的sum3却会收到左子集的元素的个数的影响,如左子集有3个元素,那么sum3[root]=sum3[ls]+sum0[rs]了,所以线段树中不仅要维护sum3还有sum0,sum1,sum2,sum4,和元素个数cnt.

代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <time.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

//#define ull unsigned __int64
#define ll __int64
//#define ull unsigned long long
//#define ll long long
#define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2
#define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1
#define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2
#define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define middle (l+r)>>1
#define MOD 1000000007
#define esp (1e-8)
const int INF=0x3F3F3F3F;
const double DINF=10000.00;
//const double pi=acos(-1.0);
const int N=100010;
int n,m,tot;
int cnt[N<<2];
ll sum[N<<2][5],X[N];
struct node{
    char op[2];
    ll x;
    void write(){
        scanf("%s",op);
        if(op[0]!='s') scanf("%I64d",&x),X[m++]=x;
    }
}a[N];

int bs(ll key,int size,ll A[]){
    int l=0,r=size-1,mid;
    while(l<=r){
        mid=middle;
        if(key>A[mid]) l=mid+1;
        else if(key<A[mid]) r=mid-1;
        else return mid;
    }return -1;
}

void PushUp(int rt){
    int i,j,k,ls=rt<<1,rs=ls|1;
    for(i=0,j=cnt[ls]%5;i<5;i++){
        k=i-j;
        sum[rt][i]=sum[ls][i]+sum[rs][k<0? k+5:k];
    }
    cnt[rt]=cnt[ls]+cnt[rs];
}

void Update(int l,int r,int rt,int p,ll c){
    if(l==r){
        cnt[rt]= c? 1:0;
        sum[rt][1]=c;
        return;
    }
    int mid=middle;
    if(p<=mid) Update(lson,p,c);
    else Update(rson,p,c);
    PushUp(rt);
}

void init(){
    int i;
    for(i=m=0;i<n;i++) a[i].write();
    sort(X,X+m);
    for(i=tot=1;i<m;i++) if(X[i]!=X[i-1]) X[tot++]=X[i];
    memset(sum,0,sizeof(sum));
    memset(cnt,0,sizeof(cnt));
}

void sof(){
    for(int i=0,pos;i<n;i++){
        if(a[i].op[0]=='s') printf("%I64d\n",sum[1][3]);
        else{
            pos=bs(a[i].x,tot,X)+1;
            if(a[i].op[0]=='a') Update(1,n,1,pos,a[i].x);
            else Update(1,n,1,pos,0);
        }
    }
}

int main(){
    //freopen("1.in","r",stdin);
    //freopen("1.out","w",stdout);
    //int T,cas;scanf("%d",&T);for(cas=1;cas<=T;cas++)
    while(~scanf("%d",&n)) init(),sof();
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值