zoukankan      html  css  js  c++  java
  • ZOJ 4053 Couleur

    4053

    思路:

    主席树

    先分别求前缀和后缀的逆序数

    然后要求某一段的逆序数,就可以根据前缀或着后缀根据容斥求出答案,

    这样需要枚举这一段中的数,求之前或者之后有多少个比他大或比他小的数,

    这个可以通过用主席数维护权值线段树来做

    然后每次枚举断开后小的那段区间,这样最多需要枚举n*log(n)次

    复杂度:n*log(n)*log(n)

    代码:

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #pragma GCC optimize(4)
    #include<bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define pi acos(-1.0)
    #define LL long long
    //#define mp make_pair
    #define pb push_back
    #define ls rt<<1, l, m
    #define rs rt<<1|1, m+1, r
    #define ULL unsigned LL
    #define pll pair<LL, LL>
    #define pii pair<int, int>
    #define piii pair<pii, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    #define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
    //head
    
    const int N = 1e5 + 10, M = 2e6 + 10;
    int a[N], p[N], root[N], bit[N], lson[M], rson[M], value[M], tot = 0, n;
    LL tmp[N], ans[N], pre[N], suf[N];
    multiset<LL> s;
    void build(int &x, int l, int r) {
        x = ++tot;
        if(l == r) {
            value[x] = 0;
            return ;
        }
        int m = l+r >> 1;
        build(lson[x], l, m);
        build(rson[x], m+1, r);
        value[x] = value[lson[x]] + value[rson[x]];
    }
    void update(int old, int &x, int p, int v, int l, int r) {
        x = ++tot;
        lson[x] = lson[old], rson[x] = rson[old], value[x] = value[old] + v;
        if(l == r) return ;
        int m = l+r >> 1;
        if(p <= m) update(lson[x], lson[x], p, v, l, m);
        else update(rson[x], rson[x], p, v, m+1, r);
    }
    int query(int L, int R, int x, int l, int r) {
        if(L > R) return 0;
        if(L <= l && r <= R) return value[x];
        int m = l+r >> 1, ans = 0;
        if(L <= m) ans += query(L, R, lson[x], l, m);
        if(R > m) ans += query(L, R, rson[x], m+1, r);
        return ans;
    }
    void add(int x, int v) {
        while(x <= n+1) bit[x] += v, x += x&-x;
    }
    int sum(int x) {
        int ans = 0;
        while(x) ans += bit[x], x -= x&-x;
        return ans;
    }
    int Find_pre(int pos) {
        int l = 1, r = pos, m = l+r >> 1;
        while(l < r) {
            if(sum(pos) - sum(m-1) > 0) l = m + 1;
            else r = m;
            m = l+r >> 1;
        }
        return m;
    }
    int Find_nxt(int pos) {
        int l = pos, r = n, m = l+r+1 >> 1;
        while(l < r) {
            if(sum(m) - sum(pos-1) > 0) r = m - 1;
            else l = m;
            m = l+r+1 >> 1;
        }
        return m;
    }
    void solve(int l, int m, int r) {
        if(l == r) return ;
        else if(l + 1 == r) {
            if(l == m) tmp[l] = 0, s.insert(0);
            else tmp[l-1] = 0, s.insert(0);
        }
        else {
            if(l == m) {
                LL t = tmp[l-1];
                t -= (query(1, a[m]-1, root[r], 1, n) - query(1, a[m]-1, root[l], 1, n));
                tmp[l] = t;
                s.insert(t);
            }
            else if(r == m) {
                LL t = tmp[l-1] - (query(a[m]+1, n, root[r-1], 1, n) - query(a[m]+1, n, root[l-1], 1, n));
                tmp[l-1] = t;
                s.insert(t);
            }
            else {
                LL t = tmp[l-1], t1, t2;
                if(m-l+1 < r-m) {
                    t1 = pre[m-1] - pre[l-1];
                    for (int i = l; i < m; i++) {
                        t1 -= query(a[i]+1, n, root[l-1], 1, n);
                    }
    
                    t2 = t - t1;
                    for (int i = l; i < m; i++) {
                        t2 -= query(1, a[i]-1, root[r], 1, n) - query(1, a[i]-1, root[m-1], 1, n);
                    }
                    t2 -= query(1, a[m]-1, root[r], 1, n) - query(1, a[m]-1, root[m], 1, n);
                 }
                else {
                    t2 = suf[m+1] - suf[r+1];
                    for (int i = m+1; i <= r; i++) {
                        if(r+1 <= n) t2 -= query(1, a[i]-1, root[n], 1, n) - query(1, a[i]-1, root[r], 1, n);
                    }
    
                    t1 = t - t2;
                    for (int i = m+1; i <= r; i++) {
                        t1 -= query(a[i]+1, n, root[m], 1, n) - query(a[i]+1, n, root[l-1], 1, n);
                    }
                    t1 -= query(a[m]+1, n, root[m-1], 1, n) - query(a[m]+1, n, root[l-1], 1, n);
                }
                tmp[l-1] = t1;
                tmp[m] = t2;
                s.insert(t1);
                s.insert(t2);
            }
        }
    
    }
    int main() {
        int T;
        scanf("%d", &T);
        while(T--) {
            scanf("%d", &n);
            for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
            for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
            pre[0] = suf[n+1] = 0; 
            s.clear();
            tot = 0;
            build(root[0], 1, n);
            for (int i = 1; i <= n; i++) update(root[i-1], root[i], a[i], 1, 1, n);
            for (int i = n; i >= 1; i--) {
                suf[i] = suf[i+1] + query(1, a[i]-1, root[n], 1, n) - query(1, a[i]-1, root[i], 1, n);
            }
            for (int i = 1; i <= n; i++) {
                pre[i] = pre[i-1] + query(a[i]+1, n, root[i-1], 1, n);
            }
            for (int i = 0; i <= n+1; i++) bit[i] = 0;
            tmp[0] = suf[1];
            s.insert(tmp[0]);
            for (int i = 1; i <= n; i++) {
                ans[i] = *s.rbegin();
                int t = ans[i]^p[i];
                int l = Find_pre(t), r = Find_nxt(t);
                s.erase(s.find(tmp[l-1]));
                solve(l, t, r);
                add(t, 1);
            }
            for (int i = 1; i <= n; i++) printf("%lld%c", ans[i], " 
    "[i==n]);
        }
        return 0;
    }
  • 相关阅读:
    hdu 3666 差分约束系统
    hdu 1198农田灌溉
    常微分方程(阿諾爾德) Page 45 相空間,相流,運動,相曲線 註記
    高等微積分(高木貞治) 1.4節 例2
    常微分方程(阿諾爾德) Page 45 相空間,相流,運動,相曲線 註記
    解析函數論 Page 29 命題(2) 函數模的有界性
    高等微積分(高木貞治) 1.4節 例2
    解析函數論 Page 29 命題(1) 有界閉集上的一致連續性
    解析函數論 Page 29 命題(3) 模的下界的可達性
    解析函數論 Page 29 命題(2) 函數模的有界性
  • 原文地址:https://www.cnblogs.com/widsom/p/9665429.html
Copyright © 2011-2022 走看看