😊 | Powered By HeartFireY |
Problem Analysis
仍然是维护区间内数字出现的次数,然后在树上暴力查询左右子节点间的值,当碰到某个节点小于等于
r
−
l
+
1
k
\frac{r - l + 1}{k}
kr−l+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;
}