zoukankan      html  css  js  c++  java
  • luoguP3690 列队

    https://www.luogu.org/problemnew/show/P3960

    作为一个初二蒟蒻要考提高组,先做一下17年的题目

    我们发现进行一次操作相当于

    • 把第 x 行的第 y 个弹出记为 a,其余向左移 = splay 中弹出第 y 个
    • 把第 m 列的第 x 个弹出记为 b,其余向上移 = splay 中弹出第 x 个
    • 把 b 插到第 x 行末尾 = splay 在队尾插入 b
    • 把 a 插到第 m 列末尾 = splay 在队尾插入 a

    然后对于没有用到的节点先合并着,要用就拆开

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    typedef unsigned long long ull;
    typedef long long ll;
    
    template <typename _T>
    inline void read(_T &f) {
        f = 0; _T fu = 1; char c = getchar();
        while(c < '0' || c > '9') {if(c == '-') fu = -1; c = getchar();}
        while(c >= '0' && c <= '9') {f = (f << 3) + (f << 1) + (c & 15); c = getchar();}
        f *= fu;
    }
    
    const int N = 300000 + 10;
    
    struct Node {
        int l, r, size, id;
        Node *ch[2];
        Node (int a, int b, int c, int d, Node *e, Node *f) {
            l = a, r = b, size = c, id = d;
            ch[0] = e, ch[1] = f;
        }
    }*root[N], *null;
    
    int w[N];
    int n, m, q;
    
    void update(Node *u) {
        u -> size = u -> ch[0] -> size + u -> ch[1] -> size + u -> r - u -> l + 1;
    }
    
    void rotate(Node *&u, int d) {
        Node *tmp = u -> ch[d];
        u -> ch[d] = tmp -> ch[d ^ 1];
        tmp -> ch[d ^ 1] = u;
        update(u); update(tmp);
        u = tmp;
    }
    
    void splay(Node *&u, int k) {
        int ltree = u -> ch[0] -> size;
        if(ltree < k && (ltree + (u -> r - u -> l + 1) >= k)) return;
        int d = k > ltree;
        int k2 = d ? k - ltree - (u -> r - u -> l + 1) : k;
        int ltree2 = u -> ch[d] -> ch[0] -> size;
        if(ltree2 >= k2 || (ltree2 + u -> ch[d] -> r - u -> ch[d] -> l + 1) < k2) {
            int d2 = k2 > ltree2;
            splay(u -> ch[d] -> ch[d2], d2 ? k2 - ltree2 - (u -> ch[d] -> r - u -> ch[d] -> l + 1) : k2);
            if(d == d2) rotate(u, d2);
            else rotate(u -> ch[d], d2);
        }
        rotate(u, d);
    }
    
    Node *build(int l, int r) {
        if(l > r) return null;
        if(l == r) return new Node(w[l], w[l], 1, w[l], null, null);
        int mid = (l + r) >> 1;
        return new Node(w[mid], w[mid], r - l + 1, w[mid], build(l, mid - 1), build(mid + 1, r));
    }
    
    void merge(Node *&a, Node *&b) {
        if(a == null) a = b, b = null;
        if(b == null) return;
        splay(a, a -> size);
        a -> ch[1] = b;
        update(a);
    }
    
    int split(Node *&u, int k) {
        splay(u, k);
        int ltree = u -> ch[0] -> size;
        int K = k - ltree, l = u -> l, r = u -> r;
        if(K != 1) {
            Node *tmp = new Node(l, l + K - 2, K - 1, l, u -> ch[0], null);
            u -> ch[0] = tmp; u -> l = l + K - 1; update(u -> ch[0]);
        }
        if(K != r - l + 1) {
            Node *tmp = new Node(l + K, r, r - l - K + 1, l + K, null, u -> ch[1]);
            u -> ch[1] = tmp; u -> r = l + K - 1; update(u -> ch[1]);
        }
        Node *t2 = u -> ch[1]; u -> ch[1] = null; u -> id = u -> l;
        int ans = u -> id; u = u -> ch[0]; merge(u, t2); return ans;
    }
    
    void ins(Node *&u, int x) {
        if(u == null) u = new Node(x, x, 1, x, null, null);
        else {
            splay(u, u -> size);
            u -> ch[1] = new Node(x, x, 1, x, null, null);
            update(u);
        }
    }
    
    signed main() {
        null = new Node(0, -1, 0, 0, 0, 0);
        read(n); read(m); read(q);
        for(int i = 1; i <= n; i++) {
            root[i] = new Node(1 + (i - 1) * m, m - 1 + (i - 1) * m, m - 1, 1 + (i - 1) * m, null, null);
        }
        for(int i = 1; i <= n; i++) w[i] = i * m;
        root[0] = build(1, n);
        for(int i = 1; i <= q; i++) {
            int a, b;
            read(a); read(b);
            if(b == m) {
                int ans = split(root[0], a);
                printf("%lld
    ", ans);
                ins(root[0], ans);
                continue;
            }
            int ans = split(root[a], b);
            printf("%lld
    ", ans);
            int tmp = split(root[0], a);
            ins(root[a], tmp);
            ins(root[0], ans);
        }
        return 0;
    }
    
  • 相关阅读:
    sql 在日期范围内搜索
    js 处理日期时间字符串显示的方法
    matlab练习程序(并行计算)
    C++程序运行时间
    matlab练习程序(KNN,K最邻近分类法)
    多媒体指令(像素处理)
    ubuntu启动/重启/停止apache
    matlab练习程序(matlab调用c/c++)
    我的vim设置
    matlab练习程序(c/c++调用matlab<engine>)
  • 原文地址:https://www.cnblogs.com/LJC00118/p/9561970.html
Copyright © 2011-2022 走看看