#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\n", ans);
}
int main() {
    int T = 1;
    // scanf("%d", &T);
    while(T --) 
        solve();
    return 0;
}
posted @ 2021-02-04 15:54  pyoxiao  阅读(60)  评论(0编辑  收藏  举报