题目:http://poj.org/problem?id=1769
看完题目一想贪心不就可以了吗,写了之后WA,看了discuss才发现自己读题都没读清楚Σ( ° △ °|||)︴
题目要求找出subsequence,想着DP就行了,令f[x]表示覆盖[1,x]的区间至少需要的sorter个数,则对于一个sorter [a,b],有f[b] = min(f[b], f[a]+1),想想又不太对,因为还需要f[b-1] = min(f[b-1], f[a] + 1),f[b-2] = min(f[b-2], f[a] + 1),一直到f[a+1] = min(f[a+1], f[a] + 1),这个复杂度就可能达到O(MN)了,肯定不行。
题目实际上可以这么理解,给一些覆盖区间,问覆盖到第N个点至少需要多少个,感觉有点像区间修改点查询,关注区间的覆盖情况,对于一个sorter [a,b],则区间[a,b]的覆盖 = a点覆盖需要 + 1
需要注意的地方:对于sorter [1, x],则区间[1,x]的覆盖 = 1
#include <cstdio>
#include <algorithm>
using namespace std;
#define MAX 50005
#define INF 999999999
int N, M;
int l[MAX << 2], r[MAX << 2], c[MAX << 2];
void build(int i, int L, int R)
{
l[i] = L;
r[i] = R;
c[i] = INF;
if(L == R) return;
int M = (L + R) >> 1;
build(i << 1, L, M);
build(i << 1 | 1, M + 1, R);
}
void update(int i, int a, int b, int k)
{
if(a <= l[i] && r[i] <= b){
c[i] = min(c[i], k);
return;
}
int m = (l[i] + r[i]) >> 1;
if(m < a) update(i << 1 | 1, a, b, k);
else if(b <= m) update(i << 1, a, b, k);
else{
update(i << 1, a, m, k);
update(i << 1 | 1, m+1, b, k);
}
}
int query(int i, int x)
{
if(l[i] == r[i]) return c[i];
c[i << 1] = min(c[i << 1], c[i]);
c[i << 1 | 1] = min(c[i << 1 | 1], c[i]);
return ((l[i] + r[i]) >> 1) >= x ? query(i << 1, x) : query(i << 1 | 1, x);
}
int main()
{
int i, x, y, e, k;
while(~scanf("%d%d", &N, &M)){
build(1, 1, N);
for(i = 0; i < M; ++i){
scanf("%d%d", &x, &y);
if(x == 1) break;
}
update(1, x, y, 1);
for(++i; i < M; ++i){
scanf("%d%d", &x, &y);
update(1, x, y, x == 1 ? 1 : query(1, x) + 1);
}
printf("%d\n", query(1, N));
}
return 0;
}