題目鏈接:
G: \
P: \
題目
飼養了 種奶牛,編號從 到 。一些品種的奶牛和其他奶牛間相處良好,事實證明,如果兩個品種的奶牛編號分別爲 ,當 時,這兩個品種的奶牛能友好相處,否則不能友好相處。
一條長長的道路貫穿整個農場,道路的左側有 個牧場(每個品種的奶牛恰好佔據一個牧場),道路的右側也有 個牧場(每個品種的奶牛恰好佔據一個牧場)。爲了讓奶牛們安全穿過馬路, 希望能在馬路上畫出一些人行道(牛行道?),要求這些人行道滿足如下條件:
人行道從左側的某個牧場出發,連接到右側的某個牧場;
人行道連接的兩個牧場的奶牛要能友好相處;
人行道不能在道路中間相交;
每個牧場只能與一條人行道相連。
你需要幫 求出最多能有多少條人行道。
輸入
輸入第一行一個整數 。
接下來 行,每行一個整數 ,代表道路左側第 個牧場的奶牛品種編號。
接下來 行,每行一個整數 ,代表道路右側第 個牧場的奶牛品種編號。
輸出
輸出最多能畫多少條人行道。
樣例輸入
6
1
2
3
4
5
6
6
5
4
3
2
1
樣例輸出
5
數據範圍
思路
這道題還是樹狀數組。
我們先記錄序列中每個值的位置,然後我們依次枚舉左側的數,然後枚舉能連的點,把這一條路作爲最後一條路,(就是說只能在它的上面建路,其實就是前綴和),看最多能畫多少條,再把這一條路加入樹狀數組中。
最後,我們只需要再輸出前綴和的第個(就是最後一個)就可以了。
代碼
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct node{
int to, go, op, next;
}e[800001];
int n, a[100001], b[100001], pl[100001], an[100001], bit[100001];
queue<int>q;
int find(int now) {//單點查值
int re = 0;
for (; now; now -= (now & -now))
re = max(re, bit[now]);
return re;
}
void build(int x, int y) {//單點加值
for (; x <= n; x += (x & -x))
if (y > bit[x]) bit[x] = y;
else return ;
}
int main() {
// freopen("nocross.in", "r", stdin);
// freopen("nocross.out", "w", stdout);
scanf("%d", &n);//讀入
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);//讀入
for (int i = 1; i <= n; i++) {
scanf("%d", &b[i]);//讀入
pl[b[i]] = i;//記錄b序列中每個值的位置
}
for (int i = 1; i <= n; i++) {
for (int j = max(1, a[i] - 4); j <= min(n, a[i] + 4); j++)//可以連邊的點
an[j] = find(pl[j] - 1);//單點求值
for (int j = max(1, a[i] - 4); j <= min(n, a[i] + 4); j++)
build(pl[j], an[j] + 1);//單點加值(因爲加上了這條邊,所以要加一)
}
printf("%d", find(n));//輸出
// fclose(stdin);
// fclose(stdout);
return 0;
}