CF840D Destiny 主席树

😊 | Powered By HeartFireY

Problem Analysis
在这里插入图片描述仍然是维护区间内数字出现的次数,然后在树上暴力查询左右子节点间的值,当碰到某个节点小于等于 r − l + 1 k \frac{r - l + 1}{k} krl+1直接终止查询向父节点回溯。

Accepted Code

#include <bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;

const int N = 5e5 + 10;

ll a[N], b[N];
ll tot, root[N << 5], sum[N << 5], lc[N << 5], rc[N << 5];

void update(int &rt, int pre, int l, int r, int k, int v){
    rt = ++tot, lc[rt] = lc[pre], rc[rt] = rc[pre], sum[rt] = sum[pre];
    if(l == r){
        sum[rt] += v;
        return;
    }
    int mid = l + r >> 1;
    if(k <= mid) update(lc[rt], lc[pre], l, mid, k, v);
    else update(rc[rt], rc[pre], mid + 1, r, k, v);
    sum[rt] = sum[lc[rt]] + sum[rc[rt]];
}

int query(int rt, int pre, int l, int r, int k){
    if(sum[rt] - sum[pre] <= k) return -1;
    if(l == r) return l;
    ll res = 1e18;
    ll mid = l + r >> 1;
    if(sum[lc[rt]] - sum[lc[pre]] > k){
        ll ans = query(lc[rt], lc[pre], l, mid, k);
        if(ans > 0) res = min(res, ans);
    }
    if(sum[rc[rt]] - sum[rc[pre]] > k){
        ll ans = query(rc[rt], rc[pre], mid + 1, r, k);
        if(ans > 0) res = min(res, ans);
    }
    return res;
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    ll n, m; cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++) update(root[i], root[i - 1], 1, n, a[i], 1);
    while(m--){
        ll l, r, k; cin >> l >> r >> k;
        ll tar = (r - l + 1) / k, ans = query(root[r], root[l - 1], 1, n, tar);
        if(ans == 1e18) cout << -1 << endl;
        else cout << ans << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HeartFireY

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值