- 33行之前是通用的线段树构建,下标从零开始
- 33行之后实现了:求数字序列的最长严格上升子序列,且相邻数的差不大于k。下标从1开始
- TODO:线段树的区间修改,动态开点
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
using ll = long long;
struct node {
ll sum;
int max;
int l;
int r;
int lazy;
} tree[400009];
void build(int l, int r, int idx, int *nums) {
tree[idx].l = l;
tree[idx].r = r;
if(l == r) {
tree[idx].sum = nums[l];
tree[idx].max = nums[l];
return;
}
int mid = (l + r) >> 1;
int ls = idx << 1 | 1, rs = ls + 1;
build(l, mid, ls, nums);
build(mid+1, r, rs, nums);
tree[idx].sum = tree[ls].sum + tree[rs].sum;
tree[idx].max = tree[ls].max;
if(tree[ls].max < tree[rs].max) tree[idx].max = tree[rs].max;
}
vector<int> tr;
int query(int ql, int qr, int idx, int l, int r) {
if(qr == 0) return 0;
if(ql <= l && r <= qr) return tr[idx];
int mid = (l+r) >> 1, lson = idx << 1, rson = lson | 1;
int res = 0;
if(ql <= mid) res = query(ql, qr, lson, l, mid);
if(qr > mid) {
int tmp = query(ql, qr, rson, mid+1, r);
if(tmp > res) res = tmp;
}
return res;
}
void modify(int lr, int val, int idx, int l , int r) {
if(l == r && l == lr) {
tr[idx] = val;
return;
}
int mid = (l+r) >> 1, lson = idx << 1, rson = lson | 1;
if(lr <= mid) modify(lr, val, lson, l, mid);
else modify(lr, val, rson, mid+1, r);
tr[idx] = tr[lson];
if(tr[rson] > tr[idx]) tr[idx] = tr[rson];
}
int main(int argc, char **argv) {
vector<int> nums = {9,10,11,12,13,14, 15};
int k = 3;
int u = *max_element(nums.begin(), nums.end());
tr.resize(u * 4);
for(int i = 0; i < nums.size(); ++i) {
int begin = nums[i]-k;
if(begin < 1) begin = 1;
int res = 1 + query(begin, nums[i]-1, 1, 1, u);
modify(nums[i], res, 1, 1, u);
}
cout << tr[1] << endl;
return 0;
}