送你一堆区间
题目背景:
分析:线段树优化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;
}