在群友在寻思下大概还是用树状数组做了
#include <bits/stdc++.h>
using namespace std;
const int MAX_ELEMENTS = 1e5 + 5;
int tree[MAX_ELEMENTS], originalValues[MAX_ELEMENTS], tempValues[MAX_ELEMENTS];
int n, rankMapping[MAX_ELEMENTS];
void updateTree(int position, int newValue) {
for (; position <= n; position += position & -position)
if (newValue < tree[position]) return;
else tree[position] = newValue;
}
int getMaxValue(int position) {
int maxVal = 0;
for (; position; position -= position & -position)
maxVal = max(maxVal, tree[position]);
return maxVal;
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &originalValues[i]);
}
for (int i = 1, value; i <= n; ++i) {
scanf("%d", &value);
rankMapping[value] = i;
}
for (int i = 1; i <= n; ++i) {
int lowerBound = max(1, originalValues[i] - 4);
int upperBound = min(n, originalValues[i] + 4);
for (int j = lowerBound; j <= upperBound; ++j) {
tempValues[j] = getMaxValue(rankMapping[j] - 1);
}
for (int j = lowerBound; j <= upperBound; ++j) {
updateTree(rankMapping[j], tempValues[j] + 1);
}
}
printf("%d\n", getMaxValue(n));
return 0;
}
tree[x]记录的是第二条岸1~x的桥总条数
为什么这个题可以用树状数组:
把树状数组就看成快查的哈希,两条格子并排,修改了第二行的一个格子,这个格子到n的所有格子都被修改,知道遇到比他大的格子停下
这里修改有点用状态机进行状态转移。
每个格子更新时都只参考这个格子之前的格子,这保证了更新直接加一就行,不会相交或重连一个格子。
而两个线重时,按大的来。
两个线相交时只会大者覆盖,只要确保第n个格子的大就行。
还是心有疑惑,为啥这样转移就是最优的
ok了,确定“不相交肯定来自自己的后面”后,这个题就是最长上升子序列