hdu5249--權值線段樹

權值線段樹,是以權值爲下標的線段樹,不像普通的線段樹一樣。
但是對於較大的數據,就需要離散化來解決空間上的不足。
權值線段樹這樣一說,有點兒像主席樹的感覺。空間上也優於主席樹。但是它對於子區間卻無能爲力。它對於一些動態的整個區間上的查詢還是比較好用。
就像hdu5249就是動態中位數,就可以這樣來處理。

附上代碼:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define For(aa,bb,cc) for(int aa=bb;aa<=cc;++aa)
#define Set(aa,bb) memset(aa,bb,sizeof(aa))
#define ls node<<1
#define rs node<<1|1
using namespace std;
const int maxn=10010;
int pre[maxn],now[maxn],tree[maxn<<2];
int n,Case;

void pushup(int node){
    tree[node]=tree[ls]+tree[rs];
}

void create_tree(int node,int l,int r){
    if(l==r){
        tree[node]=0;
        return ;
    }
    int mid=(l+r)>>1;
    create_tree(ls,l,mid);
    create_tree(rs,mid+1,r);
    pushup(node);
    return ;
}

void update(int node,int l,int r,int w,int flag){
    if(l==r){
        tree[node]+=flag;
        return ; 
    }
    int mid=(l+r)>>1;
    if(w<=mid) update(ls,l,mid,w,flag);
    else update(rs,mid+1,r,w,flag);
    pushup(node);
}

int query(int node,int l,int r,int flag){
    if(l==r) return l;
    int mid=(l+r)>>1;
    if(flag<=tree[ls]) return query(ls,l,mid,flag);
    else return query(rs,mid+1,r,flag-tree[ls]);
}

void work(){
    queue<int>q;
    ++Case;
    printf("Case #%d:\n",Case);
    For(i,1,n){
        char s[10];
        scanf("%s",s);
        if(s[0]=='i') scanf("%d",&pre[i]);
        else if(s[0]=='o') pre[i]=-1;
        else pre[i]=-2;
    }
    int sum=0;
    For(i,1,n){
        if(pre[i]>=0) now[++sum]=pre[i];
    }
    sort(now+1,now+1+sum);
    sum=unique(now+1,now+sum+1)-(now+1);
    create_tree(1,1,sum);
    For(i,1,n){
        if(pre[i]>=0){
            int tmp=lower_bound(now+1,now+1+sum,pre[i])-now;
            update(1,1,sum,tmp,1);
            q.push(pre[i]);
        }
        else if(pre[i]==-1){
            int ret=q.front();
            int tmp=lower_bound(now+1,now+1+sum,ret)-now;
            update(1,1,sum,tmp,-1);
            q.pop();
        }
        else{
            int md=query(1,1,sum,(q.size()/2)+1);
            printf("%d\n",now[md]);
        }
    }
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    while(~scanf("%d",&n)) work();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章