• 0x42 数据结构进阶树状数组


    A题 楼兰图腾

    链接:https://ac.nowcoder.com/acm/contest/1032/A

    树状数组 + 逆序对

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) (x & -x)
    typedef long long ll;
    const int maxn = 2e5 + 10;
    int a[maxn], c[maxn], l[maxn], r[maxn], n;
    void update(int p, int val) {
        while (p <= n) {
            c[p] += val;
            p += lowbit(p);
        }
    }
     
    int ask(int x) {
        int res = 0;
        while (x > 0) {
            res += c[x];
            x -= lowbit(x);
        }
        return res;
    }
     
    int main() {
        //freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false), cin.tie(0);
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        //求正序,前面有几个比a[i]大
        for (int i = 1; i <= n; i++) {
            update(a[i], 1);
            l[i] = ask(a[i] - 1);
        }
        memset(c, 0, sizeof c);
        //树状数组清零求逆序,后面有几个比a[i]大
        for (int i = n; i >= 1; i--) {
            update(a[i], 1);
            r[i] = ask(a[i] - 1);
        }
        ll ans = 0;
        //依次枚举每个点作为中间点,以该点位中心的 ‘v’ 个数显然是 left[i] * right[i]
        for (int i = 2; i <= n - 1; i++) {
            ans += 1ll * (i - l[i] - 1) * (n - i - r[i]);
        }
        cout << ans << " ";
        ans = 0;
        //同理枚举 '^'的个数
        for (int i = 2; i <= n - 1; i++) {
            ans += 1ll * l[i] * r[i];
        }
        cout << ans << endl;
        return 0;
    }
    

    B题 A Tiny Problem with intergers

    链接:https://ac.nowcoder.com/acm/contest/1032/B

    树状数组 区间修改 + 单点查询

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) (x & -x)
    typedef long long ll;
    const int maxn = 1e5 + 10;
    int tr[maxn], n, q, a, pre;
    void add(int i, int v) {
        while (i <= n) {
            tr[i] += v;
            i += lowbit(i);
        }
    }
    int getsum(int x) {
        int res = 0;
        while (x) {
            res += tr[x];
            x -= lowbit(x);
        }
        return res;
    }
    int main() {
        //freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false), cin.tie(0);
        cin >> n >> q;
        for (int i = 1; i <= n; ++i)cin >> a, add(i, a - pre), pre = a;
        char c; int u, v, a;
        while (q--) {
            cin >> c >> u;
            if (c == 'C') {
                cin >> v >> a; add(u, a), add(v + 1, - a);
            }
            else
                cout << getsum(u) << endl;
        }
    }
    

    C题 A Simple Problem with Integers

    链接:https://ac.nowcoder.com/acm/contest/1032/C

    树状数组 区间修改 + 区间查询 / (线段树 or 分块)

    #include<bits/stdc++.h>
    using namespace std;
    #define lowbit(x) (x & -x)
    typedef long long ll;
    const int maxn = 1e5 + 10;
    ll n, q, tr1[maxn], tr2[maxn], a, pre;
    void add(int x, int v) {
        for (int i = x; i <= n; i += lowbit(i)) tr1[i] += v, tr2[i] += 1ll * v * (x - 1);
    }
    ll getsum(int x) {
        long long sum = 0;
        for (int i = x; i; i -= lowbit(i)) sum += tr1[i] * x - tr2[i];
        return sum;
    }
    int main() {
        //freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false), cin.tie(0);
        cin >> n >> q;
        for (int i = 1; i <= n; i++) cin >> a, add(i, a - pre), pre = a;
        char c; int u, v, a;
        while (q--) {
            cin >> c >> u >> v;
            if (c == 'C') {
                cin >> a; add(u, a), add(v + 1, - a);  
            }
            else
                cout << getsum(v) - getsum(u - 1) << endl;
        }
    }
    

    D题 Lost Cows

    链接:https://ac.nowcoder.com/acm/contest/1032/D

    树状数组 + 二分(or倍增)

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5 + 10;
    long long tr[maxn];
    void add(int x, int v){
        if (x == 0)  return;
        while (x < maxn) {
            tr[x] += v;
            x += x & -x;
        }
    }
    long long query(int x){
        long long rec = 0;
        while (x) {
            rec += tr[x];
            x -= x & -x;
        }
        return rec;
    }
    int a[maxn], ans[maxn];
    int main(){
        freopen("in.txt", "r", stdin);
        int n; scanf("%d", &n);
        for (int i = 2; i <= n; i++)
            scanf("%d", &a[i]);
        //二分,查询前mid个数有多少1比较,更新区间
        for (int i = n; i; i--) {
            int l = 1, r = n + 1, t;
            while (l <= r) {
                int mid = l + r >> 1;
                if (query(mid) + a[i] < mid)  t = mid, r = mid - 1;
                else   l = mid + 1;
            }
            ans[i] = t;
            add(t, 1);
        }
        for (int i = 1; i <= n; i++)
            printf("%d\n", ans[i]);
    }
    
  • 相关阅读:
    对象的访问定位——如何找到对象
    对象的结构
    对象在内存中的布局-对象的创建
    java的内存模型--jmm
    redis 持久化之rdb总结
    简单说springmvc的工作原理
    抽象类和接口的区别
    hashcode和equals的作用区别及联系
    DBC物品中打包物品参数设置
    关于GOM引擎启动时显示:windows socket error: 在其上下文中,该请求的地址无效。 (10049), on API 'bind'
  • 原文地址:https://www.cnblogs.com/RioTian/p/13419480.html
Copyright © 2020-2023  润新知