zoukankan      html  css  js  c++  java
  • POJ2828:Buy Tickets——题解

    http://poj.org/problem?id=2828

    首先发现如果我们按照他的方法模拟的话,势必时间爆炸。

    所以我们从后往前推,因为我们知道最后一个的位置一定是对的,而前面的位置可以从后面推知。

    这样做的好处就是只移动一个元素而不是移动该元素往后的所有元素。

    那么怎么查询他应该在第几位就是个问题了。

    我们知道线段树怎么写吧。

    但是我们不知道线段树的其他功能还有替代部分二叉搜索树的功能。

    一个节点表示它的区间内含有的没被插入的位置有多少。

    那么我们知道对于一个pos,如果pos小于当前节点的左节点,那么我们往左走,否则减去左节点的值,走右节点。

    那么我们就做完了!

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    using namespace std;
    inline int read(){
        int X=0,w=0; char ch=0;
        while(ch<'0' || ch>'9') {w|=ch=='-';ch=getchar();}
        while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    int tree[800001],pos[200001],val[200001],ans[200001];
    void build(int a,int l,int r){
        if(l==r){
        tree[a]=1;
        return;
        }
        int mid=(l+r)>>1;
        build(a*2,l,mid);
        build(a*2+1,mid+1,r);
        tree[a]=tree[a*2]+tree[a*2+1];
        return;
    }
    void gai(int a,int l,int r,int p,int v){
        tree[a]--;
        if(l==r){
        ans[l]=v;
        return;
        }
        int mid=(l+r)>>1;
        if(tree[a*2]>p)gai(a*2,l,mid,p,v);
        else gai(a*2+1,mid+1,r,p-tree[a*2],v);
        return;
    }
    int main(){
        int n;
        while(scanf("%d",&n)!=EOF){
        build(1,0,n);
        for(int i=1;i<=n;i++){
            pos[i]=read();
            val[i]=read();
        }
        for(int i=n;i>=1;i--){
            gai(1,0,n,pos[i],val[i]);
        }
        for(int i=0;i<n;i++){
            printf("%d ",ans[i]);
        }
        printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    图论——拓扑排序
    BZOJ 2882 & 后缀数组的傻逼实现
    BZOJ 2626 & KDtree
    Colorado Potato Beetle(CF的某道) & 鬼畜宽搜
    Prime & 反素数plus
    BZOJ 2049 & LCT又一模板
    BZOJ2002 & LCT模板(分块不会搞)
    BZOJ2190 & 欧拉函数
    BZOJ 1053 & 反素数
    POJ2774 & 后缀数组模板题
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/7866632.html
Copyright © 2011-2022 走看看