送你一堆区间
题目背景:
分析:线段树优化DP
首先,考虑朴素意义下的DP,我们将区间端点变成覆盖的点集,然后按照左端点排序,考虑dp[i][j]表示,考虑到第i个区间,覆盖了前j个点的方案数,显然如果不选择那么直接考虑i - 1的dp值,如果选择第i个区间,那么原来覆盖到l - 1到r的方案数,就可以转移到dp[i][r]上,如果原来覆盖到r之后的,不会改变右端点位置,dp[i][j] += dp[i][j]就可以了,所以我们相当于将某一段的和加到某一个点上,然后区间乘2,那么拿线段树维护一下就可以了,复杂度O(nlogn)
Source:
/* created by scarlyw */ #include <cstdio> #include <string> #include <algorithm> #include <cstring> #include <iostream> #include <cmath> #include <cctype> #include <vector> #include <set> #include <queue> #include <ctime> #include <bitset> inline char read() { static const int IN_LEN = 1024 * 1024; static char buf[IN_LEN], *s, *t; if (s == t) { t = (s = buf) + fread(buf, 1, IN_LEN, stdin); if (s == t) return -1; } return *s++; } ///* template<class T> inline void R(T &x) { static char c; static bool iosig; for (c = read(), iosig = false; !isdigit(c); c = read()) { if (c == -1) return ; if (c == '-') iosig = true; } for (x = 0; isdigit(c); c = read()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x; } //*/ const int OUT_LEN = 1024 * 1024; char obuf[OUT_LEN], *oh = obuf; inline void write_char(char c) { if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf; *oh++ = c; } template<class T> inline void W(T x) { static int buf[30], cnt; if (x == 0) write_char('0'); else { if (x < 0) write_char('-'), x = -x; for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48; while (cnt) write_char(buf[cnt--]); } } inline void flush() { fwrite(obuf, 1, oh - obuf, stdout); } /* template<class T> inline void R(T &x) { static char c; static bool iosig; for (c = getchar(), iosig = false; !isdigit(c); c = getchar()) if (c == '-') iosig = true; for (x = 0; isdigit(c); c = getchar()) x = ((x << 2) + x << 1) + (c ^ '0'); if (iosig) x = -x; } //*/ const int MAXN = 500000 + 10; const int mod = 1000000000 + 9; int n, m; int a[MAXN]; struct tree { int sum, tag; } tree[MAXN << 2]; inline void add(int &x, int t) { x += t, (x >= mod) ? (x -= mod) : (x); } inline void mul_modify(int k, int x) { tree[k].sum = (long long)tree[k].sum * x % mod; tree[k].tag = (long long)tree[k].tag * x % mod; } inline void push_down(int k) { if (tree[k].tag != 1) { mul_modify(k << 1, tree[k].tag); mul_modify(k << 1 | 1, tree[k].tag); tree[k].tag = 1; } } inline void update(int k) { tree[k].sum = 0; add(tree[k].sum, tree[k << 1].sum), add(tree[k].sum, tree[k << 1 | 1].sum); } struct data { int l, r; inline bool operator < (const data &a) const { return (l == a.l) ? (r < a.r) : (l < a.l); } } inter[MAXN]; inline int binary_l(int x) { int l = -1, r = m + 1; while (l + 1 < r) { int mid = l + r >> 1; (a[mid] >= x) ? r = mid : l = mid; } return r; } inline int binary_r(int x) { int l = 0, r = m + 1; while (l + 1 < r) { int mid = l + r >> 1; (a[mid] <= x) ? l = mid : r = mid; } return l; } inline void read_in() { R(n), R(m); for (int i = 1; i <= n; ++i) R(inter[i].l), R(inter[i].r); for (int i = 1; i <= m; ++i) R(a[i]); std::sort(a + 1, a + m + 1); for (int i = 1; i <= n; ++i) { inter[i].l = binary_l(inter[i].l); inter[i].r = binary_r(inter[i].r); } std::sort(inter + 1, inter + n + 1); } inline void build(int k, int l, int r) { tree[k].tag = 1, tree[k].sum = 0; if (l == r) return ; int mid = l + r >> 1; build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r); } inline void modify(int k, int l, int r, int pos, int x) { if (l == r) return add(tree[k].sum, x); int mid = l + r >> 1; push_down(k); if (pos <= mid) modify(k << 1, l, mid, pos, x); else modify(k << 1 | 1, mid + 1, r, pos, x); update(k); } inline int query(int k, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) return tree[k].sum; int mid = l + r >> 1, ret = 0; push_down(k); if (ql <= mid) add(ret, query(k << 1, l, mid, ql, qr)); if (qr > mid) add(ret, query(k << 1 | 1, mid + 1, r, ql, qr)); return update(k), ret; } inline void mul_modify(int k, int l, int r, int ql, int qr) { if (ql <= l && r <= qr) return mul_modify(k, 2); int mid = l + r >> 1; push_down(k); if (ql <= mid) mul_modify(k << 1, l, mid, ql, qr); if (qr > mid) mul_modify(k << 1 | 1, mid + 1, r, ql, qr); update(k); } inline void dfs(int k, int l, int r) { std::cout << l << " " << r << " " << tree[k].tag << " " << tree[k].sum << '\n'; if (l == r) return ; int mid = l + r >> 1; dfs(k << 1, l, mid), dfs(k << 1 | 1, mid + 1, r); } inline void solve() { build(1, 0, m), modify(1, 0, m, 0, 1); for (int i = 1; i <= n; ++i) { int sum1 = query(1, 0, m, inter[i].l - 1, inter[i].r); if (inter[i].r != m) mul_modify(1, 0, m, inter[i].r + 1, m); modify(1, 0, m, inter[i].r, sum1); } std::cout << query(1, 0, m, m, m); } int main() { freopen("xmasinterval.in", "r", stdin); freopen("xmasinterval.out", "w", stdout); read_in(); solve(); return 0; }