1. 程式人生 > >牛客小白9 換個角度思考(離線+樹狀陣列)

牛客小白9 換個角度思考(離線+樹狀陣列)


title: 牛客小白9 換個角度思考(離線+樹狀陣列)
date: 2018-11-29 15:25:18
tags: [離線,樹狀陣列]
categories: ACM

題目連結

題目描述

給定一個序列,有多次詢問,每次查詢區間裡小於等於某個數的元素的個數
即對於詢問 (l,r,x),你需要輸出 img 的值
其中 [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; }