CF 85D 五颗线段树

突然发现这题和省赛的线段树类型一模一样的啊,可恨早没有做

 

In one well-known algorithm of finding the k-th order statistics we should divide all elements into groups of five consecutive elements and find the median of each five. A median is called the middle element of a sorted array (it's the third largest element for a group of five). To increase the algorithm's performance speed on a modern video card, you should be able to find a sum of medians in each five of the array.

sum of medians of a sorted k-element set S = {a1, a2, ..., ak}, where a1 < a2 < a3 < ... < ak, will be understood by as

 

The  operator stands for taking the remainder, that is  stands for the remainder of dividing x by y.

To organize exercise testing quickly calculating the sum of medians for a changing set was needed.

View Code
#include<cstdio>

#include<cstring>

#include<algorithm>

using namespace std;

typedef __int64 lld;

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

const int maxn = 100010;

int sum[maxn<<2];

lld ans[maxn<<2][5];

int key[maxn];

int x[maxn];

int flag;

char op[maxn][10];

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]+=2*flag-1;

    if(l==r){

        ans[rt][0]=flag*key[pos];

        return;

    }

    int m=(l+r)>>1;

    if(pos<=m) update(pos,lson);

    else update(pos,rson);

    pushup(rt);

}

int main(){

    int n,i,j,tot=0;

    scanf("%d",&n);

    for(i=0;i<n;i++){

        scanf("%s",op[i]);

        if(op[i][0]=='a' || op[i][0]=='d') scanf("%d",&x[i]),key[tot++]=x[i];

    }

    sort(key,key+tot);

    tot=unique(key,key+tot)-key;

    for(i=0;i<n;i++){

        int pos=lower_bound(key,key+tot,x[i])-key;

        if(op[i][0]=='a') flag=1,update(pos,1,tot,1);

        else if(op[i][0]=='d') flag=0,update(pos,1,tot,1);

        else printf("%I64d\n",ans[1][2]);

    }

    return 0;

}

 

你可能感兴趣的:(线段树)