• #459D-Pashmak and Parmida's problem


    题目链接

    Pashmak and Parmida's problem

    tag

    二维偏序,树状数组

    solution

    题目可以简化为计算有多少(pair(i,j)) 满足 (1 leq i leq n) (and) (1 leq j leq n) (and) (i < j) (and) (f(1, i, a[i]) > f(j, n, a[j]))

    (pre[i]) 表示(f(1, i, a[i]))(suf[i])表示(f(i, n, a[i])),由于(a[i] leq 10^9)可以利用map或者离散化前后两次遍历(O(n))求出(pre, suf)

    因为是计算对于每个(pre[i]),有多少(j > i) (and) (suf[j] < pre[i]),经典的二位偏序问题,我们维护一个表示suf[j]值出现次数的树状数组,倒着枚举(i),求出有多少(suf[j] ∈ [1, pre[i] - 1]),即(query(pre[i-1])), 然后树状数组中下标(suf[j])的值加一,即(add(suf[j], 1)),表示这个值出现的次数增加一次

    需要每次统计前缀和并且单点更新,正好是树状数组可以解决的

    code

    //created by pyoxiao on 2021/01/18
    #include<bits/stdc++.h>
    #define LL long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    #define CL(a, b) memset(a, b, sizeof(a))
    using namespace std;
    const int mod = 1e9 + 7;
    LL fpow(LL a, LL b, LL p = mod){LL ans = 1; a %= p; while(b) {if(b & 1) ans = ans * a % p; b >>= 1; a = a * a % p;} return ans;}
    LL gcd(LL a, LL b){return b == 0 ? a : gcd(b, a % b);}
    const int N = 1e6 + 7;
    int n, a[N];
    vector<int> ls;
    struct tr{
        int c[N];
        int lowbit(int x){ return x & -x; }
        void add(int x, int y) {
            while(x < N) {
                c[x] += y;
                x += lowbit(x);
            }
        }
        int ask(int x) {
            int ans = 0;
            while(x) {
                ans += c[x];
                x -= lowbit(x);
            }
            return ans;
        }
    }tt;
    int cnt[N], cnt2[N], pre[N], suf[N];
    void solve() {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) {
            scanf("%d", a + i);
            ls.pb(a[i]);
        }
        sort(ls.begin(), ls.end());
        ls.erase(unique(ls.begin(), ls.end()), ls.end());
        for(int i = 1; i <= n; i ++) {
            a[i] = lower_bound(ls.begin(), ls.end(), a[i]) - ls.begin() + 1;
        }
        for(int i = 1; i <= n; i ++) {
            pre[i] = ++ cnt[a[i]];
        }
        for(int i = n; i >= 1; i --) {
            suf[i] = ++cnt2[a[i]];
        }
        LL ans = 0;
        for(int i = n; i >= 1; i --) {
            ans += tt.ask(pre[i] - 1);
            tt.add(suf[i], 1);
        }
        printf("%lld
    ", ans);
    }
    int main() {
        int T = 1;
        // scanf("%d", &T);
        while(T --) 
            solve();
        return 0;
    }
    
  • 相关阅读:
    简单的java socket 示例
    Java Socket编程
    session的常用方法。
    Request与session与application的区别
    百度echart使用心得,百度图表。
    SpingMVC ModelAndView, Model,Control以及参数传递
    Flume理论研究与实验
    RocketMq在SparkStreaming中的应用总结
    数据实践过程中理论总结
    flink-vs.-spark
  • 原文地址:https://www.cnblogs.com/pyoxiao/p/14373054.html
Copyright © 2020-2023  润新知