注意这题的一些细节,首先当 L 为奇数的时候 dp[L] 与 dp[1] 属于同一个剩余类,那么 dp[L] 就为 ∞,所以直接可以输出 −1。其次,对于判断 i 是否在区间内,可以用一个指针 p 动态向后移动的方式来判断,如果第 p 个区间的右边界小等于 i,那么 p 就右移,知道 p 等于 n 或者右边界大于 i 为止,这时候判断第 p 个区间的左边界是否比 i 小,如果左边界小于 i,那么 dp[i] 就是 ∞。最后,如果 dp[L] 等于 ∞ 记得输出 −1。
constint MAX = 1001000; constint oo = 0x3f3f3f3f; int dp[MAX];
structSeg { int x, y; Seg(int x = 0, int y = 0) : x(x), y(y) {} booloperator<(const Seg& seg) const { return x < seg.x; } } seg[1100]; int q[MAX], id[MAX], f, b;
intmerge(int n){ int top = 0; sort(seg, seg + n); int l = seg[0].x, r = seg[0].y; for (int i = 1; i < n; i++) { if (seg[i].x < r) { r = max(r, seg[i].y); } else { seg[top++] = Seg(l, r); l = seg[i].x; r = seg[i].y; } } seg[top++] = Seg(l, r); return top; }
intmain(){ int n, L, l, r, p; scanf("%d%d", &n, &L); if (L & 1) { printf("%d\n", -1); return0; } scanf("%d%d", &l, &r); for (int i = 0; i < n; i++) { scanf("%d%d", &seg[i].x, &seg[i].y); } n = merge(n); l <<= 1; r <<= 1; dp[0] = 0; f = b = 0; p = 0; dp[0] = 0; for (int i = 2; i < l; i += 2) dp[i] = oo; // start with 2. for (int i = l; i <= L; i += 2) { while (f != b && i - id[f] > r) f++; while (f != b && q[b - 1] >= dp[i - l]) b--; id[b] = i - l; q[b++] = dp[i - l]; while (p < n && seg[p].y <= i) p++; // if q[f] is oo, not to set dp[i] = q[f]+1. else dp[i]=q[f]+1; if (p < n && seg[p].x < i || q[f] == oo) dp[i] = oo; } // for(int i=0;i<=L;i+=2)printf("%d ",dp[i]==oo?-1:dp[i]);puts(""); printf("%d\n", dp[L] == oo ? -1 : dp[L]); return0; }