poj 2761 Feed the dogs

原题链接:http://poj.org/problem?id=2761

Treap的做法。具体实现如下:

#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#define N 50020  
#define Max_N 100020  
#define A_Seed 16807  
#define INF 0x7fffffff  
#define Q_Seed (INF / A_Seed)  
#define R_Seed (INF % A_Seed)  
#define node_size(x) (((x)==NULL) ? 0 : ((x)->size))  
typedef struct node_t{ int left,right,k,id,ans; }node;  
node rec[N];  
typedef struct treap_t{  
    int pretty,fix,size;  
    struct treap_t *left,*right;  
}treap,*Treap;  
treap _treap[Max_N<<2];  
int sz,pair[Max_N];  
static int seed=1;  
int Redom(){  
    int hi=seed / Q_Seed;  
    int lo=seed % Q_Seed;  
    int temp = A_Seed * lo - R_Seed * hi;  
    return temp > 0 ? (seed = temp) : (seed = temp + INF);  
}  
void rotate_right(Treap *T){  
    Treap k=(*T)->left;  
    (*T)->left=k->right;  
    k->right=*T;  
    (*T)->size=node_size((*T)->left)+node_size((*T)->right)+1;  
    k->size=node_size(k->left)+node_size(k->right)+1;  
    *T=k;  
}  
void rotate_left(Treap *T){  
    Treap k=(*T)->right;  
    (*T)->right=k->left;  
    k->left=*T;  
    (*T)->size=node_size((*T)->left)+node_size((*T)->right)+1;  
    k->size=node_size(k->left)+node_size(k->right)+1;  
    *T=k;  
}  
void Insert(Treap *T,int pretty,int fix){  
    if(*T == NULL){  
        *T=&_treap[sz++];  
        (*T)->left=(*T)->right=NULL;  
        (*T)->pretty=pretty,(*T)->size=1,(*T)->fix=fix;  
    }else if(pretty < (*T)->pretty){  
        Insert(&((*T)->left),pretty,fix);  
        if((*T)->left->fix < (*T)->fix)  
            rotate_right(T);  
        (*T)->size=node_size((*T)->left)+node_size((*T)->right)+1;  
    }else if(pretty >= (*T)->pretty){  
        Insert(&((*T)->right),pretty,fix);  
        if((*T)->right->fix < (*T)->fix)  
            rotate_left(T);  
        (*T)->size=node_size((*T)->left)+node_size((*T)->right)+1;  
    }  
}  
void Remove(Treap *T,int pretty){  
    if(pretty == (*T)->pretty){  
        if((*T)->left==NULL || (*T)->right==NULL){  
            if((*T)->left!=NULL)  
                *T=(*T)->left;  
            else  
                *T=(*T)->right;  
        }else if((*T)->left->fix < (*T)->right->fix){  
            rotate_right(T);  
            (*T)->size--;  
            Remove(&((*T)->right),pretty);  
        }else if((*T)->left->fix > (*T)->right->fix){  
            rotate_left(T);  
            (*T)->size--;  
            Remove(&((*T)->left),pretty);  
        }  
    }else if(pretty < (*T)->pretty){  
        (*T)->size--;  
        Remove(&((*T)->left),pretty);  
    }else{  
        (*T)->size--;  
        Remove(&((*T)->right),pretty);  
    }  
}  
Treap find_kth(Treap T,int k){  
    int x = node_size(T->left);  
    if(k < x + 1 ) return find_kth(T->left,k);  
    else if(x + 1 < k) return find_kth(T->right,k-(x+1));  
    return T;  
}  
void swap(int *a,int *b){  
    int t=*a;  
    *a=*b;  
    *b=t;  
}  
int cmp(const void *a,const void *b){  
    node t1=*(node *)a,t2=*(node *)b;  
    return t1.left - t2.left;  
}  
int cmp_t(const void *a,const void *b){  
    node t1=*(node *)a,t2=*(node *)b;  
    return t1.id - t2.id;  
}  
int main()  
{  
#ifdef LOCAL  
    freopen("input.txt","r",stdin);  
#endif  
    int i,r,l,n,m;  
    while(EOF!=scanf("%d %d",&n,&m)){  
        sz=0;  
        Treap T=NULL;  
        memset(pair,0,sizeof(pair));  
        for(i=1;i<=n;i++) scanf("%d",&pair[i]);  
        for(i=1;i<=m;i++){  
            scanf("%d %d %d",&rec[i].left,&rec[i].right,&rec[i].k);  
            if(rec[i].left > rec[i].right) swap(&rec[i].left,&rec[i].right);  
            rec[i].id=i;  
        }  
        qsort(&rec[1],m,sizeof(rec[0]),cmp);  
        l=rec[1].left,r=0;  
        for(i=1;i<=m;i++){  
            while(rec[i].left > l) if(l <= r) Remove(&T,pair[l++]);  
            while(rec[i].right < r) Remove(&T,pair[--r]);  
            if(r < l) r=l;  
            while(r <= rec[i].right) Insert(&T,pair[r++],Redom());  
            rec[i].ans=find_kth(T,rec[i].k)->pretty;  
        }  
        qsort(&rec[1],m,sizeof(rec[0]),cmp_t);  
        for(i=1;i<=m;i++) printf("%d\n",rec[i].ans);  
    }  
    return 0;  
} 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值