HDU - 5324 Boring Class
Posted ichneumon
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 5324 Boring Class相关的知识,希望对你有一定的参考价值。
cdq分治+树状数组
很久没写cdq分治了,大概有两年了?
求答案最小字典序有个小trick,倒着求一个f[i]表示以i开始最长的序列长度,最后输出的时候从前往后扫f,第一个等于答案且满足前面已经选定的点带来的限制的点就可以添加到答案序列里来。
cdq分治求解中先处理后半部分,再计算后半部分的贡献,再计算前半部分。注意,计算贡献需要按某一维排序,然后类似归并地处理,用bit来取max,但递归前半部分时需要恢复序列按id的增序。
#include <bits/stdc++.h> using namespace std; const int MAXN = 5e4 + 100; struct Point { int x, y; int id; } p[MAXN]; int f[MAXN]; bool cmp(const Point&a, const Point&b) { return a.id < b.id; } bool cmp2(const Point&a, const Point&b) { return a.x < b.x || (a.x == b.x && (a.y > b.y || (a.y == b.y && a.id < b.id))); } int b[MAXN * 2]; void upd(int p, int v) { //b[p] = v; //return ; for (; p < MAXN * 2; b[p] = max(b[p], v), p += p&-p); } void clr(int p) { //b[p] = 0; //return ; for (; p < MAXN * 2; b[p] = 0, p += p&-p); } int qry(int p) { int r = 0; //for (int i = 1; i <= p; ++i) // r = max(r, b[i]); //return r; for (; 0 < p; r = max(r, b[p]), p -= p&-p); return r; } void cdq(int l, int r) { if (l == r) return ; int m = (l + r) >> 1; cdq(m + 1, r); sort(p + m + 1, p + r + 1, cmp2); sort(p + l, p + m + 1, cmp2); for (int i = m, j = r; l <= i; --i) { while (m < j && p[i].x <= p[j].x) upd(p[j].y, f[p[j].id]), --j; f[p[i].id] = max(f[p[i].id], 1 + qry(p[i].y)); } for (int j = r; m < j; --j) clr(p[j].y); sort(p + l, p + m + 1, cmp); cdq(l, m); } int main() { #ifdef lol freopen("code.in", "r", stdin); freopen("code.out", "w", stdout); #endif int n; while (scanf("%d", &n) != EOF) { int c = 0, *t = new int[n * 2]; for (int i = 1; i <= n; ++i) scanf("%d", &p[i].y), t[c++] = p[i].y; for (int i = 1; i <= n; ++i) scanf("%d", &p[i].x), t[c++] = p[i].x; sort(t, t + c); for (int i = 1; i <= n; ++i) { p[i].x = lower_bound(t, t + c, p[i].x) - t + 1; p[i].y = lower_bound(t, t + c, p[i].y) - t + 1; p[i].id = i; f[i] = 1; } delete t; cdq(1, n); sort(p + 1, p + n + 1, cmp); int ans = 0; for (int i = 1; i <= n; ++i) { ans = max(ans, f[i]); } printf("%d\n", ans); for (int i = 1, j = 0; i <= n; ++i) if (f[i] == ans && (j == 0 || (p[j].x <= p[i].x && p[i].y <= p[j].y))) { printf("%d%c", i, " \n"[(--ans) == 0]); j = i; } } return 0; }
以上是关于HDU - 5324 Boring Class的主要内容,如果未能解决你的问题,请参考以下文章
HDU - 5324:Boring Class (CDQ分治&树状数组&最小字典序)