NOIP2017:列队

Sol

考场上:
这不是送 50 50 吗, Q2 Q 2 递推就好了
然后,怎么又送 20 20 分???
woc w o c ,只有半个小时了,顺利没调出来只有 50 50
考后:
TM T M 一个大于号写成小于号。。。
20 20 分没了
TAT T A T


正解的一种

n n 棵线段树维护每一行的前m1
再开一棵维护最后一列的情况
长度为 max(n,m)+q m a x ( n , m ) + q
动态开点
每次就变成删除节点,插入节点了
维护区间元素个数
查找就是全局第 k k <script type="math/tex" id="MathJax-Element-631">k</script>小

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
const int _(3e5 + 5);
typedef long long ll;

IL int Input(){
    RG int x = 0, z = 1; RG char c = getchar();
    for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
    for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
    return x * z;
}

int n, m, q, rt[_], num, len, tp, tail[_], now;
struct Segment{
    int ls, rs, sz;
    ll val;
} T[_ * 40];

IL int Size(RG int l, RG int r){
    if(now == n + 1){
        if(r <= n) return r - l + 1;
        if(l <= n) return n - l + 1;
        return 0;
    }
    if(r < m) return r - l + 1;
    if(l < m) return m - l;
    return 0;
}

IL ll Query(RG int &x, RG int l, RG int r, RG int p){
    if(!x) x = ++num, T[x].sz = Size(l, r);
    --T[x].sz;
    if(l == r){
        if(!T[x].val) T[x].val = (now == n + 1) ? 1LL * l * m : 1LL * (now - 1) * m + l;
        return T[x].val;
    }
    RG int mid = (l + r) >> 1, sz = T[x].ls ? T[T[x].ls].sz : Size(l, mid);
    if(p <= sz) return Query(T[x].ls, l, mid, p);
    return Query(T[x].rs, mid + 1, r, p - sz);
}

IL void Modify(RG int &x, RG int l, RG int r, RG int p, RG ll v){
    if(!x) x = ++num, T[x].sz = Size(l, r);
    ++T[x].sz;
    if(l == r){
        T[x].sz = 1, T[x].val = v;
        return;
    }
    RG int mid = (l + r) >> 1;
    if(p <= mid) Modify(T[x].ls, l, mid, p, v);
    else Modify(T[x].rs, mid + 1, r, p, v);
}

int main(RG int argc, RG char* argv[]){
    n = Input(), m = Input(), q = Input(), len = max(n, m) + q;
    for(RG int i = 1; i <= n; ++i) T[rt[i] = ++num].sz = tail[i] = m - 1;
    T[rt[n + 1] = ++num].sz = tail[n + 1] = n;
    for(RG int i = 1; i <= q; ++i){
        RG int x = Input(), y = Input(); RG ll id1, id2;
        if(y == m){
            now = n + 1, id1 = Query(rt[n + 1], 1, len, x);
            ++tail[n + 1], Modify(rt[n + 1], 1, len, tail[n + 1], id1);
        }
        else{
            now = x, id1 = Query(rt[x], 1, len, y);
            ++tail[now = n + 1], Modify(rt[n + 1], 1, len, tail[n + 1], id1);
            id2 = Query(rt[n + 1], 1, len, x);
            ++tail[now = x], Modify(rt[x], 1, len, tail[x], id2);
        }
        printf("%lld\n", id1);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值