[线段树|平衡树|树状数组]LightOJ - 1087 - Diablo

1087 - Diablo
Time Limit:2 second(s) Memory Limit:64 MB

All of you must have played the game 'Diablo'. It's an exclusive game to play. In this game the main opponent of you is Diablo. If you kill him the game finishes. But as usual, Diablo is smarter than you.

Diablo has a large number of army. Diablo arranges them in a line in any arbitrary order and everyone is given an integer id. Each time Diablo either adds one army in the end or he calls for thektharmy (from left) from the line. Then the army gets out and it attacks you.

Since you are a great magician, you can read Diablo's mind. Now you want to find the id of the armies who are about to attack you.

Input

Input starts with an integerT (≤ 5), denoting the number of test cases.

The first line of each case is a blank line. The next line contains two integersn (0 ≤ n ≤ 105), denoting the number of the initial army andq (1 ≤ q ≤ 50000)representing the number of queries. The next line containsnspace separated integers. Theithinteger of this line denotes the id of theithperson. Each of these integers will be positive and fits into a 32 bit signed integer. Each of the nextqlines will contain a query, of the form:

a p(add a person at the end of the line whose id isp)

c k(call thekthperson from the line (from left),kis a positive 32 bit signed integer)

Output

For each case of input, print the case number in a line. Then for all the queries'c k'you have to print theidof thekthperson or'none'if there is none.

Sample Input

Output for Sample Input

2

5 5

6 5 3 2 1

c 1

c 1

a 20

c 4

c 4

2 1

18811 1991

c 1

Case 1:

6

5

20

none

Case 2:

18811


看完题立马想到平衡树,以数的插入顺序建立一颗平衡树,查询和删除第K小即可,然后又想到维护一个区间和,二分求出区间和为k的位置,然后该位置的数就是所求,这种方法可以用线段树或者树状数组实现,不多说了,水题直接上代码。

各种蛋疼:好久没写这些数据结构了,手好生啊,调了半天。

平衡树版本-SBT

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 111111;
struct TNode{
    int l,r,idx,val,size;
    void clearNode(){
        l = r = size = 0;
    }
    void initNode(int idx,int val){
        this->idx = idx, this->val = val;
        l = r = 0; size = 1;
    }
};
struct SBT{
    TNode Node[MAXN];
    int pool[MAXN],top,cnt,rt;
    void init(){
        top = cnt = rt = 0;
    }
    int Malloc(int id,int v){
        int x;
        if(top!=0){
            x = pool[--top];
        }else{
            x = ++cnt;
        }
        Node[x].initNode(id,v);
        return x;
    }
    void Free(int x){
        pool[top++] = x;
        Node[x].clearNode();
    }
    void left_rotate(int &p){
        TNode &fa = Node[p];
        TNode &son = Node[fa.r];
        int q = fa.r;//node idx of son
        fa.r = son.l; son.l = p;
        son.size = fa.size;
        fa.size = Node[fa.l].size+Node[fa.r].size+1;
        p = q;
    }
    void right_rotate(int &p){
        TNode &fa = Node[p];
        TNode &son = Node[fa.l];
        int q = fa.l;
        fa.l = son.r, son.r = p;
        son.size = fa.size;
        fa.size = Node[fa.l].size+Node[fa.r].size+1;
        p = q;
    }
    void Maintain(int &p,bool flag){
        TNode cur = Node[p];
        if(!flag){
            if(Node[Node[cur.l].l].size>Node[cur.r].size){
                right_rotate(p);
            }else if(Node[Node[cur.l].r].size>Node[cur.r].size){
                left_rotate(cur.l);
                right_rotate(p);
            }else{
                return;
            }
        }else{
            if(Node[Node[cur.r].r].size>Node[cur.l].size){
                left_rotate(p);
            }else if(Node[Node[cur.r].l].size>Node[cur.l].size){
                right_rotate(cur.r);
                left_rotate(p);
            }else{
                return;
            }
        }
        Maintain(cur.l,0);
        Maintain(cur.r,1);
        Maintain(p,0);
        Maintain(p,1);
    }
    void Insert(int &p,int idx,int val){
        if(!p){
            p = Malloc(idx,val);
            return;
        }else{
            Node[p].size++;
            if(idx<Node[p].idx)Insert(Node[p].l,idx,val);
            else Insert(Node[p].r,idx,val);
            Maintain(p,idx>=Node[p].idx);
        }
    }
    int Delete(int &p,int idx){
        Node[p].size--;
        if(Node[p].idx==idx||(Node[p].l==0&&idx<Node[p].idx)||(Node[p].r==0&&idx>Node[p].idx)){
            int q = p;
            if(Node[p].l==0||Node[p].r==0){
                p = Node[p].l+Node[p].r;
                Node[q].clearNode();
                return q;
            }else{
                int cur = Delete(Node[p].r,idx+1);
                int tidx = Node[p].idx, tval = Node[p].val;
                Node[p].idx = Node[cur].idx, Node[p].val = Node[cur].val;
                Node[cur].idx = tidx, Node[cur].val = tval;
                return cur;
            }
        }
        if(idx<Node[p].idx)return Delete(Node[p].l,idx);
        else return Delete(Node[p].r,idx);
    }
    int Select(int p,int k){
        int rank = Node[Node[p].l].size+1;
        if(rank==k)return p;
        else if(rank<k)return Select(Node[p].r,k-rank);
        else return Select(Node[p].l,k);
    }
}T;
int main(){
    int Tot,N,Q,IDX,val;
    scanf("%d",&Tot);
    for(int cas=1;cas<=Tot;cas++){
        T.init();
        scanf("%d%d",&N,&Q);
        IDX = 0;
        while(N--){
            scanf("%d",&val);
            T.Insert(T.rt,IDX++,val);
        }
        printf("Case %d:\n",cas);
        while(Q--){
            char op[3];
            scanf("%s%d",op,&val);
            if(op[0]=='c'){
                if(T.Node[T.rt].size<val){
                    printf("none\n");
                }else{
                    int x = T.Select(T.rt,val);
                    x = T.Delete(T.rt,T.Node[x].idx);
                    printf("%d\n",T.Node[x].val);
                }
            }else{
                T.Insert(T.rt,IDX++,val);
            }
        }
    }
    return 0;
}


线段树版本:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int MAXN = 111111;
const int BD = MAXN+50000;
int sum[(BD)<<2],record[BD];
void build(int l,int r,int rt){
    sum[rt]=0;
    if(l==r)return;
    int m = (l+r)>>1;
    build(lson); build(rson);
}
void update(int pos,int c,int l,int r,int rt){
    if(l==r){
        //cout<<l<<" "<<c<<" "<<sum[rt]<<endl;
        sum[rt]=c;
        return;
    }
    int m = (l+r)>>1;
    if(pos<=m)update(pos,c,lson);
    else update(pos,c,rson);
    sum[rt] = sum[rt<<1]+sum[rt<<1|1];
}
int query(int k,int l,int r,int rt){
    if(l==r)return l;
    int m = (l+r)>>1;
    if(sum[rt<<1]>=k)return query(k,lson);
    else return query(k-sum[rt<<1],rson);
}
int main(){
    int T,N,Q,M;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d%d",&N,&Q);M = N+1;
        build(1,BD,1);
        for(int i=1;i<=N;i++)scanf("%d",&record[i]),update(i,1,1,BD,1);
        printf("Case %d:\n",cas);
        while(Q--){
            char op[3];
            int k;
            scanf("%s%d",op,&k);
            //cout<<"tot:"<<sum[1]<<endl;system("pause");
            if(op[0]=='c'){
                if(sum[1]<k){
                    printf("none\n");
                }else{
                    int pos = query(k,1,BD,1);//cout<<pos<<" "<<endl;
                    //system("pause");
                    update(pos,0,1,BD,1);
                    printf("%d\n",record[pos]);
                }
            }else{
                record[M] = k;
                update(M,1,1,BD,1);
                M++;
            }
        }
    }
    return 0;
}


树状数组版本:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 155555;
int sum[MAXN+1],arr[MAXN];
int lowbit(int x){
    return x&(-x);
}
int query(int pos){
    int s = 0;
    while(pos>0){
        s+=sum[pos];
        pos -= lowbit(pos);
    }
    return s;
}
void add(int pos,int c){
    while(pos<=MAXN){
        sum[pos]+=c;
        pos += lowbit(pos);
    }
}
int main(){
    int T,N,Q,M,CNT;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++){
        scanf("%d%d",&N,&Q);M = N+1;CNT = N;
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=N;i++){
            scanf("%d",&arr[i]);
            add(i,1);
        }
        printf("Case %d:\n",cas);
        while(Q--){
            char op[3];int k;
            scanf("%s%d",op,&k);
            //cout<<query(MAXN)<<endl;system("pause");
            if(op[0]=='c'){
                if(CNT<k){
                    printf("none\n");
                    continue;
                }
                CNT--;
                int l = 1,r = MAXN,m;
                while(l<=r){
                    m = (l+r)>>1;
                    if(k<=query(m))r = m-1;
                    else l = m+1;
                }
                //cout<<l<<" "<<query(l)<<endl;system("pause");
                printf("%d\n",arr[l]);
                add(l,-1);
            }else{
                CNT++;
                arr[M] = k;
                add(M++,1);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值