POJ

题意

输入队伍长度n
接下来n行,a,b 表示b插在队伍的a处
求队伍最后的情况

题解

刚开始并不知道要用线段树,经大佬点悟,发现最后插入的位置就是对应的a。所以可以从后往前依次插入,每次的位置pos即找到一个位置pos使它前面空出pos个位置。然后我们就可以用线段树了。
常数巨大的丑陋代码

# include <stdio.h>
# include <stdlib.h>
# include <iostream>
# include <string.h>
# include <algorithm>
using namespace std;

# define IL inline
# define RG register
# define UN unsigned
# define ll long long
# define rep(i, a, b) for(RG int i = a; i <= b; i++)
# define per(i, a, b) for(RG int i = b; i >= a; i--)
# define uev(e, u) for(RG int e = ft[u]; e != -1; e = edge[e].nt)
# define mem(a, b) memset(a, b, sizeof(a))
# define max(a, b) ((a) > (b)) ? (a) : (b)
# define min(a, b) ((a) < (b)) ? (a) : (b)

const int MAXN = 200001, MAXM = 1000001;
struct Tree{
    int l, r, num;
} tree[MAXM];
int n, ans, pos[MAXN], val[MAXN], a[MAXN];

IL void Updata(RG int now){
    tree[now].num = tree[now<<1].num+tree[now<<1|1].num;
}

IL void Build(RG int now, RG int l, RG int r){
    tree[now] = (Tree) {l, r, 1};
    if(l == r) return;
    RG int mid = l+r>>1;
    Build(now<<1, l, mid); Build(now<<1|1, mid+1, r);
    Updata(now);
}

IL int Query(RG int now, RG int x){
    if(tree[now].l == tree[now].r) return tree[now].r;
    if(x <= tree[now<<1].num) return Query(now<<1, x);
    else return Query(now<<1|1, x-tree[now<<1].num);
}

IL void Add(RG int now, RG int x){
    if(tree[now].l == tree[now].r){
        tree[now].num = 0;
        return;
    }
    RG int mid = tree[now].l+tree[now].r>>1;
    if(mid < x) Add(now<<1|1, x);
    if(mid >= x) Add(now<<1, x);
    Updata(now);
}

int main(){
    while(~scanf("%d", &n)){
        Build(1, 1, n);
        rep(i, 1, n) scanf("%d%d", &pos[i], &val[i]), pos[i]++;
        per(i, 1, n){
            RG int t = Query(1, pos[i]);
            a[t] = val[i];
            Add(1, t);
        }
        rep(i, 1, n) printf("%d ", a[i]);
        printf("
");
    }
    return 0;
}

scanf前没写~居然TLE了三次

原文地址:https://www.cnblogs.com/cjoieryl/p/8206414.html