牛客小白9 換個角度思考(離線+樹狀陣列)
阿新 • • 發佈:2018-12-28
title: 牛客小白9 換個角度思考(離線+樹狀陣列)
date: 2018-11-29 15:25:18
tags: [離線,樹狀陣列]
categories: ACM
題目描述
給定一個序列,有多次詢問,每次查詢區間裡小於等於某個數的元素的個數
即對於詢問 (l,r,x),你需要輸出 的值
其中 [exp] 是一個函式,它返回 1 當且僅當 exp 成立,其中 exp 表示某個表示式
輸入描述:
第一行兩個整數n,m 第二行n個整數表示序列a的元素,序列下標從1開始標號,保證1 ≤ ai ≤ 105 之後有m行,每行三個整數(l,r,k),保證1 ≤ l ≤ r ≤ n,且1 ≤ k ≤ 105
輸出描述:
對於每一個詢問,輸出一個整數表示答案後回車
輸入
5 1
1 2 3 4 5
1 5 3
輸出
3
備註:
資料範圍
1 ≤ n ≤ 105
1 ≤ m ≤ 105
思路
- 將原陣列和要查詢的K值升序排列,這樣能保證前面小的數的貢獻對後面也有影響
- 然後用樹狀陣列維護
#include <bits/stdc++.h>
#define N 100006
#define mem(a, b) memset(a, b, sizeof(a))
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
using namespace std;
struct ac{
int val, id, l, r;
}a[N], b[N];
int ans[N], c[N];
int n, m;
void update(int x, int d) {
while (x <= n) {
c[x] += d;
x += lowbit(x);
}
}
int query(int x) {
int ans = 0;
while (x) {
ans += c[ x];
x -= lowbit(x);
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
scanf("%d %d", &n, &m);
// 讀入陣列,並記錄序號
for (int i = 0; i < n; ++i) {
scanf("%d", &a[i].val);
a[i].id = i + 1;
}
// 讀入查詢,記錄序號
for (int i = 0; i < m; ++i) {
scanf("%d %d %d", &b[i].l, &b[i].r, &b[i].val);
b[i].id = i + 1;
}
// 分別升序排列
sort(a, a + n, [&](const ac &x, const ac &y){
return x.val < y.val;
});
sort(b, b + m, [&](const ac &x, const ac &y){
return x.val < y.val;
});
// j列舉原陣列 1-n 的數字
int j = 0;
for (int i = 0; i < m; ++i) {
// 存在小於當前查詢的K值,就樹狀陣列更新貢獻
while (j < n && a[j].val <= b[i].val) {
update(a[j].id, 1);
++j;
}
// 將答案按照序號儲存在陣列中
ans[b[i].id] = query(b[i].r) - query(b[i].l - 1);
}
for (int i = 1; i <= m; ++i) {
printf("%d\n", ans[i]);
}
return 0;
}