子序列中任意两个相邻元素的差值不超过 k的子序列个数

给定一个长度为 n 的整数数组 nums,要求统计所有满足以下条件的子序列‌的个数

子序列‌:定义为从原数组中按顺序选取的元素组成的序列(不要求连续)。 

子序列中任意两个相邻元素的差值不超过 k(即 |nums[i] - nums[j]| ≤ k)。 

结果取模‌:由于答案可能很大,输出结果对 10^9 + 7 取模。

输入格式‌

第一行:整数 n 和 k(1 ≤ n ≤ 10^5,0 ≤ k ≤ 10^9)。

第二行:n 个整数,表示数组 nums(-10^9 ≤ nums[i] ≤ 10^9)。 ‌

输出格式‌

一个整数,表示满足条件的子序列个数。

知识点

函数条件用法
lower_bound 第一个 ≥ value的位置

vector<int> v = {1, 3, 3, 5, 7};
auto it = lower_bound(v.begin(), v.end(), 3);
// it 指向第一个3(索引1)

upper_bound 第一个 > value的位置

vector<int> v = {1, 3, 3, 5, 7};
auto it = upper_bound(v.begin(), v.end(), 3);
// it 指向5(索引3)

#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;

class FenwickTree {
public:
    vector<long long> tree;
    int size;
    
    FenwickTree(int n) {
        size = n;
        tree.resize(size + 1, 0);
    }
    
    void update(int i, long long val) {
        while (i <= size) {
            tree[i] = (tree[i] + val) % MOD;
            i += i & -i;
        }
    }
    
    long long query(int i) {
        long long res = 0;
        while (i > 0) {
            res = (res + tree[i]) % MOD;
            i -= i & -i;
        }
        return res;
    }
    
    long long rangeQuery(int l, int r) {
        return (query(r) - query(l - 1) + MOD) % MOD;
    }
};

int countSubsequences(vector<int>& nums, int k) {
    int n = nums.size();
    
    // 离散化
    vector<int> sorted = nums;
    sort(sorted.begin(), sorted.end());
    sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end());
    
    unordered_map<int, int> indexMap;
    for (size_t i = 0; i < sorted.size(); ++i) {
        indexMap[sorted[i]] = i + 1; // 从1开始编号
    }
    
    FenwickTree ft(sorted.size());
    
    long long result = 0;
    
    for (int i = 0; i < n; ++i) {
        int current = nums[i];
        int currentIndex = indexMap[current];
        
        // 查询范围 [current - k, current + k] 对应的离散化索引
        int left = lower_bound(sorted.begin(), sorted.end(), current - k) - sorted.begin() + 1;
        int right = upper_bound(sorted.begin(), sorted.end(), current + k) - sorted.begin();
        
        long long count = 1; // 当前元素本身
        if (left <= right) {
            count = (count + ft.rangeQuery(left, right)) % MOD;
        }
        
        result = (result + count) % MOD;
        ft.update(currentIndex, count);
    }
    
    return result;
}

int main() {
    int n, k;
    cin >> n >> k;
    vector<int> nums(n);
    for (int i = 0; i < n; ++i) {
        cin >> nums[i];
    }
    
    int result = countSubsequences(nums, k);
    cout << result << endl;
    
    return 0;
}

 

posted @ 2025-07-27 22:30  最近饭吃的很多  阅读(17)  评论(0)    收藏  举报