题目:
给一个长为的,落在
上的区间序列,问最短的子序列,相邻区间有交集,连续覆盖
上所有点。
。
做法:
线段树上每个叶子表示上的一个点,维护当前延伸到
需要的最短区间序列长度。一开始设结点1为0,其他点为
。每次读入一个区间
,
左端点
,即用已有的区间延伸到
所需的最短区间序列长度,设为
。然后用
,
线段树上
区间的值。最后
终点
的值即为答案。
代码:
#include <cstdio>
#include <algorithm>
#define lson rt<<1
#define rson rt<<1|1
#define IOS ios::sync_with_stdio(false), cin.tie(0)
#define debug(a) cout << #a ": " << a << endl
using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
int lazy[N<<2];
void build(int l, int r, int rt){
lazy[rt] = inf;
if (l == r){
if (l == 1) lazy[rt] = 0;
return;
}
int mid = (l+r) >> 1;
build(l, mid, lson);
build(mid+1, r, rson);
}
void pushdown(int rt){
lazy[lson] = min(lazy[lson], lazy[rt]);
lazy[rson] = min(lazy[rson], lazy[rt]);
lazy[rt] = inf;
}
void update(int L, int R, int x, int l, int r, int rt){
if (L <= l && r <= R){
lazy[rt] = min(lazy[rt], x); return;
}
if (lazy[rt] != inf) pushdown(rt);
int mid = (l+r) >> 1;
if (L <= mid) update(L, R, x, l, mid, lson);
if (R > mid) update(L, R, x, mid+1, r, rson);
}
int query(int pos, int l, int r, int rt){
if (l == r) return lazy[rt];
if (lazy[rt] != inf) pushdown(rt);
int mid = (l+r) >> 1;
if (pos <= mid) return query(pos, l, mid, lson);
else return query(pos, mid+1, r, rson);
}
int main(void){
int n, m; scanf("%d%d", &n, &m);
build(1, n, 1);
for (int i = 1; i <= m; ++i){
int l, r; scanf("%d%d", &l, &r);
int k = query(l, 1, n, 1);
update(l, r, k+1, 1, n, 1);
}
printf("%d\n", query(n, 1, n, 1));
return 0;
}

京公网安备 11010502036488号