poj2828(线段树解插队问题)

来源:互联网 发布:mac版beyond compare 编辑:程序博客网 时间:2024/05/01 04:24

题目链接:poj2828

/*题意:    n个人,每一行两个数,pos和val,pos表示这个价值为val的数要插入到位置为pos的数后面,最后按位置顺序输出思路:线段树    考虑倒着插入队列,因为后插入队列的元素一定不会受到先插入队列元素的影响每次插入时,我们考虑当前结点左儿子中空位的个数    如果左儿子中的空位置个数s[rt<<1].sum>=num,向左儿子中插    如果左儿子中的空位置个数s[rt<<1].sum<num,向右儿子中插*/#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define lson l, mid, rt<<1#define rson mid+1, r, rt<<1|1const int N = 200000;int pos[N],val[N],ans[N],k;struct node{    int l,r;    int sum;}s[N<<2];void build(int l, int r, int rt){    s[rt].l = l;    s[rt].r = r;    s[rt].sum = 1;//1表示空位置    if(l == r) return;    int mid = (l+r) >> 1;    build(lson);    build(rson);    s[rt].sum = s[rt<<1].sum + s[rt<<1|1].sum;}void updata(int l, int r, int rt, int num){    if(s[rt].l == s[rt].r){        s[rt].sum = 0;//        k = s[rt].l;        return ;    }    int mid = (l+r) >> 1;    if(num <= s[rt<<1].sum)//左儿子中空位足够        updata(lson, num);    else        updata(rson, num - s[rt<<1].sum);//往右边插,同时减去左边空位。。    s[rt].sum = s[rt<<1].sum + s[rt<<1|1].sum;}int main(){    int n,i;    while(~scanf("%d",&n))    {        build(1, n, 1);        for(i = 0; i < n; i ++)            scanf("%d%d",&pos[i],&val[i]), pos[i]++;        for(i = n - 1; i >= 0; i --){            updata(1, n, 1, pos[i]);            ans[k] = val[i];        }        for(i = 1; i <= n; i ++){            if(i != 1) printf(" ");            printf("%d",ans[i]);        }        printf("\n");    }    return 0;}


0 0
原创粉丝点击