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;
    }
  • 相关阅读:
    message:"iconv(): Detected an illegal character in input string"
    VM Mac OS 无法开机
    你的爱 歌词
    大脑结构 | 前脑 | 中脑 | 后脑 | 脑干 | 大脑发育
    【分布计算环境笔记】10 SOA、网格计算、云计算与P2P技术
    【职场Tips】Language in IBM——献给所有即将成为IBMer的童鞋
    【系统工程师的自我修养】sed篇
    【Java学习笔记】如何写一个简单的Web Service
    Unison(双向同步软件)的安装与配置【转】
    发生java.lang.OutOfMemoryError: Direct buffer memory【转】
  • 原文地址:https://www.cnblogs.com/widsom/p/9665429.html
Copyright © 2011-2022 走看看