您的位置:首页 > 其它

[DP][CDQ分治] BZOJ 4553: [Tjoi2016&Heoi2016]序列

2018-03-03 13:52 609 查看

SolutionSolution

设位置ii最大可变成riri,最小lili。

fifi为ii位置的答案。容易得到fi=max{fj+1|j<i,rj≤ai,aj≤li}fi=max{fj+1|j<i,rj≤ai,aj≤li}把(rj,aj)(rj,aj)当作二位平面的一个点,((ai,li),(0,0))((ai,li),(0,0))看作一个矩形。

就是一个类似二维数点的问题。

直接CDQCDQ分治就好了。

O(nlog2n)O(nlog2⁡n)

#include <bits/stdc++.h>
#define show(x) cerr << #x << " = " << x << endl
using namespace std;
typedef long long ll;
typedef pair<int, int> Pairs;

const int N = 202020;

inline char get(void) {
static char buf[100000], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, 100000, stdin);
if (S == T) return EOF;
}
return *S++;
}
template<typename T>
inline void read(T &x) {
static char c; x = 0; int sgn = 0;
for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
if (sgn) x = -x;
}

int n, m, q, x, y, clc;
int mx
, vis
;
int a
, l
, r
;
int f
;
struct cpp {
int x, y, z, id, tp;
cpp(int _x = 0, int _y = 0, int _z = 0, int i = 0, int t = 0):
x(_x), y(_y), z(_z), id(i), tp(t) {}
inline bool operator <(const cpp &b) const {
return x < b.x;
}
};
cpp b
;

inline void update(int x, int a) {
for (x; x <= m; x += x & -x)
if (vis[x] != clc) {
mx[x] = a; vis[x] = clc;
} else mx[x] = max(mx[x], a);
}
inline int query(int x) {
int mx = 0;
for (; x; x -= x & -x)
if (vis[x] == clc)
mx = max(mx, ::mx[x]);
return mx;
}
inline void divAndConq(int l, int r) {
static cpp tmp
;
if (l == r) return;
int mid = (l + r) >> 1;
int s1 = l, s2 = mid + 1;
for (int i = l; i <= r; i++)
if (b[i].z <= mid) tmp[s1++] = b[i];
else tmp[s2++] = b[i];
for (int i = l; i <= r; i++) b[i] = tmp[i];
divAndConq(l, mid);
++clc;
int j = l;
for (int i = mid + 1; i <= r; i++) {
for (; j <= mid && b[j].x <= b[i].x; j++)
if (b[j].tp == 0)
update(b[j].y, f[b[j].id]);
if (b[i].tp == 1)
f[b[i].id] = max(f[b[i].id], query(b[i].y) + 1);
}
divAndConq(mid + 1, r);
int s = l; s1 = l; s2 = mid + 1;
while (s1 <= mid && s2 <= r)
if (b[s1] < b[s2]) tmp[s++] = b[s1++];
else tmp[s++] = b[s2++];
while (s1 <= mid) tmp[s++] = b[s1++];
while (s2 <= r) tmp[s++] = b[s2++];
for (int i = l; i <= r; i++) b[i] = tmp[i];
}

int main(void) {
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
read(n); read(q);
for (int i = 1; i <= n; i++) {
read(a[i]); f[i] = 1;
l[i] = r[i] = a[i];
}
while (q--) {
read(x); read(y);
l[x] = min(l[x], y);
r[x] = max(r[x], y);
}
for (int i = 1; i <= n; i++)
m = max(r[i], m);
q = 0;
for (int i = 1; i <= n; i++) {
b[++q] = cpp(a[i], l[i], q, i, 1);
b[++q] = cpp(r[i], a[i], q, i, 0);
}
sort(b + 1, b + q + 1);
divAndConq(1, q);
cout << *max_element(f + 1, f + n + 1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: