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;
}

 

posted @ 2012-06-04 05:15  Because Of You  Views(703)  Comments(1Edit  收藏  举报