CF961E(主席树)

题意: 给出一串数字序列,寻找像 a i > j , a j > i a_i>j,a_j>i ai>j,aj>i这种数字对的数量。
思路: 根据题意可以列出 ∑ i = 1 n − 1 ∑ j = i + 1 n [ a i ≥ j ] [ a j ≥ i ] \sum_{i=1}^{n-1}\sum_{j=i+1}^{n}[a_i \geq j][a_j \geq i] i=1n1j=i+1n[aij][aji]
计算这个式子的数量就好。大于 n n n的按 n n n算。主席树模板题。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 3e5 + 10;
int n, q, a[N], root[N], cnt;
vector<int> v;
struct node {
    int l, r, num;
} zxs[N * 40];
void add(int l, int r, int pre, int &now, int pos) {
    zxs[++cnt] = zxs[pre], now = cnt, zxs[cnt].num++;
    if(l == r)
        return;
    int m = (l + r) >> 1;
    if(pos <= m)
        add(l, m, zxs[pre].l, zxs[cnt].l, pos);
    else
        add(m + 1, r, zxs[pre].r, zxs[cnt].r, pos);
}
int query(int k, int l, int r, int L, int R) {//求比k小的数的个数
    if(k > r)
        return zxs[R].num - zxs[L].num;
    int m = (l + r) >> 1, ans = 0;
    if(k > l)
        ans += query(k, l, m, zxs[L].l, zxs[R].l);
    if(k > m + 1)
        ans += query(k, m + 1, r, zxs[L].r, zxs[R].r);
    return ans;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        a[i] = min(n, a[i]);
        add(1, n, root[i - 1], root[i], a[i]);
    }
    ll ans = 0;
    for(int i = 1; i <= n - 1; i++)
        if(a[i] > i)
            ans += (a[i] - i - query(i, 1, n, root[i - 1], root[a[i]]));
    printf("%lld", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值