题目描述
佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给她。
玩具上有一个数列,数列中某些项的值可能会变化,但同一个时刻最多只有一个值发生变化。现在佳媛姐姐已经研究出了所有变化的可能性,她想请教你,能否选出一个子序列,使得在任意一种变化和原序列中,这个子序列都是不降的?请你告诉她这个子序列的最长长度即可。
输入格式
输入的第一行有两个正整数 n,m,分别表示序列的长度和变化的个数。
接下来一行有 n 个整数,表示这个数列原始的状态。
接下来 m 行,每行有 2 个整数 x,y,表示数列的第 x 项可以变化成 y 这个值。
输出格式
输出一个整数,表示对应的答案。
输入输出样例
输入 #1复制
3 4
1 2 3
1 2
2 3
2 1
3 4
输出 #1复制
3
说明/提示
注意:每种变化最多只有一个值发生变化。
在样例输入中,所有的变化是:
1 2 3
2 2 3
1 3 3
1 1 3
1 2 4
选择子序列为原序列,即在任意一种变化中均为不降子序列。
对于 20% 数据,所有数均为正整数,且小于等于 300。
对于 50% 数据,所有数均为正整数,且小于等于 3000。
对于 100% 数据,所有数均为正整数,且小于等于 105。1≤x≤n。
代码实现:
cpp
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 100005
int n, m;
class BIT
{
private:
int tr[MAXN];
int lowbit(int &x) { return x & (-x); }
public:
void clear(int pos) { for (Int i = pos; i <= n; i += lowbit(i)) tr[i] = 0; }
void upd(int pos, int x) { for (Int i = pos; i <= n; i += lowbit(i)) tr[i] = max(tr[i], x); }
int qry(int pos) { int res = 0; for (Int i = pos; i; i -= lowbit(i)) res = max(res, tr[i]); return res; }
} tree;
struct nd
{
int val, minv, maxv, id; // 原权值、最小权值、最大权值、编号
} a[MAXN];
int dp[MAXN];
bool cmp_val(nd A, nd B) { return A.val < B.val; }
bool cmp_min(nd A, nd B) { return A.minv < B.minv; }
bool cmp_id(nd A, nd B) { return A.id < B.id; }
void cdq(int l, int r)
{
if (l == r) return;
int mid = (l + r) >> 1;
cdq(l, mid);
sort(a + l, a + mid + 1, cmp_val);
sort(a + mid + 1, a + r + 1, cmp_min);
int i = l, j = mid + 1;
for (; j <= r; ++j)
{
while (i <= mid && a[i].val <= a[j].minv) tree.upd(a[i].maxv, dp[a[i].id]), i++;
dp[a[j].id] = max(dp[a[j].id], tree.qry(a[j].val) + 1);
}
while (i > l) tree.clear(a[--i].maxv);
sort(a + mid + 1, a + r + 1, cmp_id);
cdq(mid + 1, r);
}
int rd()
{
int x = 0; char c = getchar(); int f = 1;
while (c < '0' || c > '9') { if (c == '-') f = -f; c = getchar(); }
while (c >= '0' && c <= '9') { x = (x << 3) + (x << 1) + c - '0'; c = getchar(); }
return x * f;
}
void wt(int x)
{
if (x < 0) { x = -x; putchar('-'); }
if (x > 9) wt(x / 10);
putchar(x % 10 + '0');
}
signed main()
{
n = rd(), m = rd();
for (Int i = 1; i <= n; ++i) a[i].val = a[i].minv = a[i].maxv = rd(), a[i].id = i;
for (Int i = 1; i <= m; ++i)
{
int x = rd(), y = rd();
a[x].minv = min(a[x].minv, y);
a[x].maxv = max(a[x].maxv, y);
}
for (Int i = 1; i <= n; ++i) dp[i] = 1;
cdq(1, n);
int max_res = 0;
for (Int i = 1; i <= n; ++i) max_res = max(max_res, dp[i]);
wt(max_res), putchar('\n');
return 0;
}