zoukankan      html  css  js  c++  java
  • Luogu 3759 [TJOI2017]不勤劳的图书管理员

    再也不作死写FhqTreap作内层树了,卡的不如暴力呜呜呜…… 

    题意翻译:给一个序列,每个下标包含两个属性$a$和$v$,求第一个属性与下标形成的所有逆序对的第二个属性和,给出$m$个交换两个下标的操作,每次操作之后查询。

    考虑一下交换之后会发生什么:

    假设这次要交换$x$和$y$,使$x leq y$。

    发现交换之后$x, y$和$x$的左边的数和$y$右边的数构成的逆序对产生的贡献不变,发生变化的是中间的数。

    那么问题就简单了,只要先消去中间的数和$x, y$的贡献,具体来说就是$[x + 1, y - 1]$这个区间中$a_{i}$比$a_{x}$小的$b_{i}$和,以及$a_{i}$比$a_{y}$大的$b_{i}$和。

    发现$(x, y)$可能也会构成一个逆序对,拎出来判一下可以保证这一对只被计算一次。

    然后算一下交换之后产生的贡献,方法类似。

    树套树维护即可。

    时间复杂度$O(nlog^{2}n)$。

    Code:

    #include <cstdio>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int N = 5e4 + 5;
    const int M = 2e7 + 5;
    const ll P = 1e9 + 7;
    
    int n, m, a[N];
    ll v[N], ans = 0LL;
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    template <typename T>
    inline void swap(T &x, T &y) {
        T t = x; x = y; y = t;
    }
    
    namespace BinaryIndexTree {
        int cnt[N]; ll s[N];
        
        #define lowbit(x) (x & (-x))
        
        inline void modifyS(int p, ll val) {
            for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P;
        }
        
        inline void modifyC(int p) {
            for(; p <= n; p += lowbit(p)) cnt[p]++;
        }
        
        inline ll getSum(int p) {
            ll res = 0;
            for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P;
            return res;
        }
        
        inline int getCnt(int p) {
            int res = 0;
            for(; p > 0; p -= lowbit(p)) res += cnt[p];
            return res;
        }
        
        #undef lowbit
        
    } using namespace BinaryIndexTree;
    
    namespace Tree {
        int nodeCnt, root[N * 30];
        struct Node {
            int lc, rc, siz;
            ll sum;
        } s[M];
        
        #define mid ((l + r) >> 1)
        
        inline void up(int p) {
            if(!p) return;
            s[p].siz = s[s[p].lc].siz + s[s[p].rc].siz;
            s[p].sum = (s[s[p].lc].sum + s[s[p].rc].sum) % P;
        }
        
        void modify(int &p, int l, int r, int x, ll selV) {
            if(!p) p = ++nodeCnt;
            if(l == r) {
                s[p].siz = (selV != -1);
                s[p].sum = (selV == -1 ? 0 : selV % P);
                return;
            }
            
            if(x <= mid) modify(s[p].lc, l, mid, x, selV);
            else modify(s[p].rc, mid + 1, r, x, selV);
            up(p);
        }
        
        ll query(int p, int l, int r, int x, int y, ll selV) {
            if(!p) return 0LL;
            if(x <= l && y >= r) return (selV * s[p].siz % P + s[p].sum) % P;
            
            ll res = 0LL;
            if(x <= mid) res = (res + query(s[p].lc, l, mid, x, y, selV)) % P;
            if(y > mid) res = (res + query(s[p].rc, mid + 1, r, x, y, selV)) % P;
            return res;
        }
        
        #define lowbit(p) (p & (-p))
        
        inline void change(int p, int val, ll selV) {
            for(; p <= n; p += lowbit(p))
                modify(root[p], 1, n, val, selV);
        }
        
        inline void clear(int p, int val) {
            for(; p <= n; p += lowbit(p))
                modify(root[p], 1, n, val, -1);
        }
        
        inline ll ask(int p, int v, ll selV, int type) {
            ll res = 0LL;
            for(; p > 0; p -= lowbit(p)) {
                if(type) res = (res + query(root[p], 1, n, v + 1, n, selV)) % P;
                else res = (res + query(root[p], 1, n, 1, v - 1, selV)) % P;
            }
            return res;
        }
        
        inline ll qSum(int l, int r, int v, ll selV, int type) {
            return (ask(r, v, selV, type) - ask(l - 1, v, selV, type) + P) % P;
        }
        
    } using namespace Tree;
    
    int main() {
        read(n), read(m);
        nodeCnt = 0;
        for(int i = 1; i <= n; i++) {
            read(a[i]), read(v[i]);
            ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P;
            modifyS(a[i], v[i]), modifyC(a[i]);
            change(i, a[i], v[i]);
        }
        
        for(int x, y; m--; ) {
            read(x), read(y);
            if(x == y) {
                printf("%lld
    ", ans);
                continue;
            }
            if(x > y) swap(x, y);
            
            ll res = 0LL;
            if(x + 1 <= y - 1) {
                res = (res + qSum(x + 1, y - 1, a[y], v[y], 1)) % P;
                res = (res + qSum(x + 1, y - 1, a[x], v[x], 0)) % P;
            }
            if(a[y] < a[x]) res = ((res + v[x]) % P + v[y]) % P;
            
            ans = (ans - res + P) % P;
            
            res = 0LL;
            if(x + 1 <= y - 1) {
                res = (res + qSum(x + 1, y - 1, a[y], v[y], 0)) % P;
                res = (res + qSum(x + 1, y - 1, a[x], v[x], 1)) % P;
            }
            
            if(a[y] > a[x]) res = ((res + v[x]) % P + v[y]) % P;
            ans = (ans + res) % P;
            
            printf("%lld
    ", ans);
            
            clear(x, a[x]), clear(y, a[y]);
            change(x, a[y], v[y]), change(y, a[x], v[x]);
            swap(a[x], a[y]), swap(v[x], v[y]);
        }
        
        return 0;
    }
    树状数组套线段树(100 pts)
    // luogu-judger-enable-o2
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    
    const int N = 5e4 + 5;
    const int M = 2e7 + 5;
    const ll P = 1e9 + 7;
    
    int n, m, a[N];
    ll v[N], ans = 0;
    
    namespace FhqTreap {
        int root[M], nodeCnt, ch[M][2], pri[M], siz[M];
        ll key[M], sum[M], sel[M];
        
        #define lc ch[p][0]
        #define rc ch[p][1]
        
        inline void up(int p) {
            if(p) {
                siz[p] = siz[lc] + siz[rc] + 1;
                sum[p] = (sum[lc] % P + sum[rc] % P + sel[p] % P) % P;
            }
        }
        
        inline int newnode(ll val, ll selV) {
            ++nodeCnt;
            key[nodeCnt] = val, sum[nodeCnt] = sel[nodeCnt] = selV;
            pri[nodeCnt] = rand(), siz[nodeCnt] = 1;
            return nodeCnt;
        }
        
        void split(int p, ll val, int &x, int &y) {
            if(!p) x = y = 0;
            else {
                if(val >= key[p])
                    x = p, split(rc, val, rc, y);
                else 
                    y = p, split(lc, val, x, lc);
                up(p);
            }
        }
        
        int merge(int x, int y) {
            if(!x || !y) return x + y;
            else {
                if(pri[x] < pri[y]) {
                    ch[x][1] = merge(ch[x][1], y);
                    up(x);
                    return x;
                } else {
                    ch[y][0] = merge(x, ch[y][0]);
                    up(y);
                    return y;
                }    
            }    
        }
        
        inline void insert(int rt, ll val, ll selV) {
            if(!root[rt]) {
                root[rt] = newnode(val, selV);
                return;
            }
            int x, y;
            split(root[rt], val, x, y);
            root[rt] = merge(x, merge(newnode(val, selV), y));
        }
        
        inline void remove(int rt, ll val) {
            int x, y, z;
            split(root[rt], val, x, y);
            split(x, val - 1, x, z);
            z = merge(ch[z][0], ch[z][1]);
            root[rt] = merge(merge(x, z), y);
        }
        
        inline ll ask(int rt, ll val, ll selV, int type) {
            int x, y; ll res;
            if(type) {
                split(root[rt], val, x, y);
                res = (selV * siz[x] % P + sum[x]) % P; 
            } else {
                split(root[rt], val, x, y);
                res = (selV * siz[y] % P + sum[y]) % P;
            }
            root[rt] = merge(x, y);
            return res % P;
        }
        
        void Pi(int p, int *arr) {
            if(lc) Pi(lc, arr);
            printf("%d ", arr[p]);
            if(rc) Pi(rc, arr);
        }
        
        #undef lc
        #undef rc
    };
    
    namespace SegT {
        using namespace FhqTreap;
        
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        
        void ins(int p, int l, int r, int x, ll val, ll selV) {
            insert(p, val, selV);
            if(l == r) return;
            if(x <= mid) ins(lc, l, mid, x, val, selV);
            else ins(rc, mid + 1, r, x, val, selV);
        }
        
        void del(int p, int l, int r, int x, ll val) {
            remove(p, val);
            if(l == r) return;
            if(x <= mid) del(lc, l, mid, x, val);
            else del(rc, mid + 1, r, x, val);
        }
        
        ll query(int p, int l, int r, int x, int y, ll val, ll selV, int type) {
            if(x <= l && y >= r) return ask(p, val, selV, type) % P;
            
            ll res = 0;
            if(x <= mid) res = (res + query(lc, l, mid, x, y, val, selV, type)) % P;
            if(y > mid) res = (res + query(rc, mid + 1, r, x, y, val, selV, type)) % P;
            return res;
        }
        
        void print(int p, int l, int r, int *arr) {
            Pi(root[p], arr), printf("
    ");
            if(l == r) return;
            print(lc, l, mid, arr), print(rc, mid + 1, r, arr);
        }
        
    } using namespace SegT;
    
    template <typename T>
    inline void swap(T &x, T &y) {
        T t = x;
        x = y;
        y = t;
    }
    
    namespace IOstream{
        const int L = 1 << 15;
        
        char buffer[L], *S, *T;
        
        inline char Getchar() {
            if(S == T) {
                T = (S = buffer) + fread(buffer, 1, L, stdin);
                if(S == T) return EOF;
            }
            return *S++;
        }
        
        template <class T> 
        inline void read(T &X) {
            char ch; T op = 1;
            for(ch = Getchar(); ch > '9' || ch < '0'; ch = Getchar())
                if(ch == '-') op = -1;
            for(X = 0; ch >= '0' && ch <= '9'; ch = Getchar()) 
                X = (X << 1) + (X << 3) + ch - '0'; 
            X *= op;
        }
        
        template <typename T>
        inline void write(T x)
        {
            T sta[15]; int len = 0;
            if(x < 0) putchar('-'), x = -x;
            if(x == 0) {
                putchar('0');
                return;
            }
            for(; x > 0; sta[++len] = x % 10, x /= 10);
            for(int i = len; i >= 1; i--) putchar(sta[i] + '0');
        }
        
    } using namespace IOstream;
    
    namespace BinaryIndexTree {
        int cnt[N]; ll s[N];
        
        #define lowbit(x) (x & (-x))
        
        inline void modifyS(int p, ll val) {
            for(; p <= n; p += lowbit(p)) s[p] = (s[p] + val) % P;
        }
        
        inline void modifyC(int p) {
            for(; p <= n; p += lowbit(p)) cnt[p]++;
        }
        
        inline ll getSum(int p) {
            ll res = 0;
            for(; p > 0; p -= lowbit(p)) res = (res + s[p]) % P;
            return res;
        }
        
        inline int getCnt(int p) {
            int res = 0;
            for(; p > 0; p -= lowbit(p)) res += cnt[p];
            return res;
        }
        
    } using namespace BinaryIndexTree;
    
    int main() {
    //    freopen("1.in", "r", stdin);
    //    freopen("mine.out", "w", stdout);
        
    //    srand(19260817);
        
        read(n), read(m);
        nodeCnt = 0;
        for(int i = 1; i <= n; i++) {
            read(a[i]), read(v[i]);
            ans = (ans + (getSum(n) - getSum(a[i]) + P) % P + P + v[i] * (getCnt(n) - getCnt(a[i])) % P + P) % P;
            modifyS(a[i], v[i]), modifyC(a[i]);
            ins(1, 1, n, i, a[i], v[i]);
        }
        
    //    printf("%d
    ", ans);
        
        for(int x, y; m--; ) {
            read(x), read(y);
            if(x == y) {
                printf("%lld
    ", ans);
                continue;
            }
            if(x > y) swap(x, y);
            
            ll res = 0;
            if(x + 1 <= y - 1) {
                res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 0)) % P;
                res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 1)) % P; 
            }
            if(a[y] < a[x]) res = (res % P + v[x] % P + v[y] % P) % P;
            ans = (ans - res + P) % P;
            
            res = 0;
            if(x + 1 <= y - 1) {
                res = (res + query(1, 1, n, x + 1, y - 1, a[y], v[y], 1)) % P;
                res = (res + query(1, 1, n, x + 1, y - 1, a[x], v[x], 0)) % P; 
            }
            if(a[y] > a[x]) res = (v[y] % P + v[x] % P + res % P) % P;
            ans = (ans + res) % P;
            
            write(ans), puts("");
            
            del(1, 1, n, x, a[x]), del(1, 1, n, y, a[y]);
            ins(1, 1, n, y, a[x], v[x]), ins(1, 1, n, x, a[y], v[y]);
            swap(a[x], a[y]), swap(v[x], v[y]);
            
    /*        print(1, 1, n, key), printf("
    ");
            print(1, 1, n, sel), printf("
    ");   */
        }
        
        return 0;
    }
    线段树套fhqTreap (20 pts)
  • 相关阅读:
    HDU 1010 Tempter of the Bone
    HDU 4421 Bit Magic(奇葩式解法)
    HDU 2614 Beat 深搜DFS
    HDU 1495 非常可乐 BFS 搜索
    Road to Cinema
    Sea Battle
    Interview with Oleg
    Spotlights
    Substring
    Dominating Patterns
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9577938.html
Copyright © 2011-2022 走看看