F - 序列 HYSBZ - 4553
\(n, m\)分别表示序列的长度和变化的个数。
接下来一行有\(n\)个数,表示这个数列原始的状态
接下来\(m\)行,每行有2个数\(x, y\),表示数列的第\(x\)项可以变化成\(y\)这个值
最多使用一种变化, 求在所有可能的情况下都非减的最长子序列的长度
\(1 <= x <= n\) 所有数字均为正整数,且小于等于\(100,000\)
Sample Input
3 4 1 2 3 1 2 2 3 2 1 3 4
Sample Output
3
题解
一开始看错题意了,注意在所有可能情况下都是非减
设\(lea[i],big[i]\)分别为\(i\)最小和最大的变动
合法子序列中任意两相邻的\(i,j\)满足\(big[i]\leq a[j] \&\&a[i]\leq lea[j]\)
那么将左区间以\(big\)排序,右区间以\(a\)排序,再用树状数组维护\(a和lea\)即可
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 10;
const LL INF = 2147483647;
inline int in()
{
int x = 0, flag = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') flag = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();
return x * flag;
}
int n, m;
int f[MAXN];
struct Fenwick
{
int va[MAXN];
void dec(int pos)
{
for (int i = pos; i <= 100000; i += (i & (-i))) va[i] = 0;
}
void upd(int pos, int v)
{
if (va[pos] >= v) return;
va[pos] = v;
for (int i = pos; i <= 100000; i += (i & (-i))) va[i] = max(va[i], v);
}
int qry(int x)
{
int ret = -1;
for (int i = x; i > 0; i &= (i - 1)) ret = max(ret, va[i]);
return ret;
}
} T;
struct Node
{
int val, lea, big, id;
} a[MAXN], b[MAXN];
bool cmpv(Node x, Node y) { return x.val < y.val; }
bool cmpb(Node x, Node y) { return x.big < y.big; }
bool cmpi(Node x, Node y) { return x.id < y.id; }
void solve(int l, int r)
{
if (l >= r) return ;
int mid = (l + r) >> 1;
solve(l, mid);
sort(a + l, a + mid + 1, cmpb);
sort(a + mid + 1, a + r + 1, cmpv);
int i = l, j = mid + 1, k = l;
while (k <= r)
{
k ++;
if (j > r || (i <= mid && a[i].big <= a[j].val))
{
T.upd(a[i].val, f[a[i].id]);
i ++;
}
else
{
f[a[j].id] = max(f[a[j].id], T.qry(a[j].lea) + 1);
j ++;
}
}
for (int i = l; i <= mid; i ++) T.dec(a[i].val);
sort(a + mid + 1, a + r + 1, cmpi);
solve(mid + 1, r);
}
int main()
{
n = in(); m = in();
for (int i = 1; i <= n; i ++) a[i].val = a[i].lea = a[i].big = in(), a[i].id = i, f[i] = 1;
for (int i = 1; i <= m; i ++)
{
int id = in(), va = in();
a[id].lea = min(a[id].lea, va);
a[id].big = max(a[id].big, va);
}
solve(1, n);
int ans = -1;
for (int i = 1; i <= n; i ++) ans = max(ans, f[i]);
printf("%d\n", ans);
return 0;
}
/*
*/