[BZOJ1537][POI2005]Aut- The Bus
Description
Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个数(i, j) 表示(1 <= i <= n, 1 <= j <= m). Byte City里有一条公交线, 在某一些路口设置了公交站点. 公交车从 (1, 1) 发车, 在(n, m)结束.公交车只能往北或往东走. 现在有一些乘客在某些站点等车. 公交车司机希望在路线中能接到尽量多的乘客.帮他想想怎么才能接到最多的乘客.
Input
第一行三个数n, m 和 k – 表示北南走向的路的个数以及西东走向的路和乘客等车的站点的个数. ( 1 <= n <= 10^9, 1 <= m <= 10^9, 1 <= k <= 10^5). 接下来k 行每行描述一个公交站的信息.第 i + 1 行三个正整数 xi, yi 和 pi, 1 <= xi <= n, 1 <= yi <= m, 1 <= pi <= 10^6. 表示在(xi, yi) 有 pi 个乘客在等车. 每个路口在数据中最多出现一次,乘客总数不会超过1 000 000 000.
Output
一个数表示最多能接到的乘客数量.
Sample Input
8 7 11
4 3 4
6 2 4
2 3 2
5 6 1
2 5 2
1 5 5
2 1 1
3 1 1
7 7 1
7 4 2
8 6 2
4 3 4
6 2 4
2 3 2
5 6 1
2 5 2
1 5 5
2 1 1
3 1 1
7 7 1
7 4 2
8 6 2
Sample Output
11
显然的DP,设$f[i]$表示最后一个接了第$i$个车站的最多接的人数。
然后$f[i] = max(f[j]) + p[i]$,$j$满足$x[j] \leq x[i]$ and $y[j] \leq y[i]$.
于是我们可以把坐标按$x$轴从小到大排序,$x$相同按$j$从小到大排序,因为我们在更新$y$更大的时候的答案的时候可能从$y$更小的转移过来。
我们已经保证了所有的可能转移过来的$j$的$x[j]$是小于等于$x[i]$的, 我们只要保证$y[j] \leq y[i]$就行了。
这样我们可以用树状数组维护纵坐标小于等于$y[i]$的最大值。
对了坐标值的范围太大需要把纵坐标离散化。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; #define reg register inline char gc() { static const int bs = 1 << 22; static unsigned char buf[bs], *st, *ed; if (st == ed) ed = buf + fread(st = buf, 1, bs, stdin); return st == ed ? EOF : *st++; } #define gc getchar inline int read() { int res=0;char ch=gc();bool fu=0; while(!isdigit(ch))fu|=(ch=='-'), ch=gc(); while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48), ch=gc(); return fu?-res:res; } #define N 1000005 int n, m, K; int ans; struct date { int x, y, p; bool operator < (const date a) const { if (x == a.x) return y < a.y; return x < a.x; } }da[N]; int f[N]; int tr[N]; int cpy[N], u; inline void change(int x, int y) { while(x <= u) { tr[x] = max(tr[x], y); x += x & -x; } } inline int query(int x) { int res = 0; while(x) { res = max(res, tr[x]); x -= x & -x; } return res; } int main() { n = read(), m = read(), K = read(); for (reg int i = 1, t ; i <= K ; i ++) da[i] = (date){read(), t = read(), read()}, cpy[i] = t; sort(cpy + 1, cpy + 1 + K); u = unique(cpy + 1, cpy + 1 + K) - cpy - 1; for (reg int i = 1 ; i <= K ; i ++) da[i].y = lower_bound(cpy + 1, cpy + 1 + u, da[i].y) - cpy; sort(da + 1, da + 1 + K); for (reg int i = 1 ; i <= K ; i ++) { f[i] = query(da[i].y) + da[i].p; change(da[i].y, f[i]); ans = max(ans, f[i]); } cout << ans << endl; return 0; }