Why Did the Cow Cross the Road II G & Why Did the Cow Cross the Road II P

Why Did the Cow Cross the Road II GWhy\ Did\ the\ Cow\ Cross\ the\ Road\ II\ G

&\&

Why Did the Cow Cross the Road II PWhy\ Did\ the\ Cow\ Cross\ the\ Road\ II\ P

題目鏈接:

G:luogu P6119luogu\ P6119 \ jozj 6689jozj\ 6689

P:luogu P3657luogu\ P3657 \ jozj6685jozj 6685

題目

Farmer JohnFarmer\ John 飼養了 NN 種奶牛,編號從 11NN。一些品種的奶牛和其他奶牛間相處良好,事實證明,如果兩個品種的奶牛編號分別爲 a,ba,b,當 ab4|a-b| \leq 4 時,這兩個品種的奶牛能友好相處,否則不能友好相處。

一條長長的道路貫穿整個農場,道路的左側有 NN 個牧場(每個品種的奶牛恰好佔據一個牧場),道路的右側也有 NN 個牧場(每個品種的奶牛恰好佔據一個牧場)。爲了讓奶牛們安全穿過馬路,Farmer JohnFarmer\ John 希望能在馬路上畫出一些人行道(牛行道?),要求這些人行道滿足如下條件:

人行道從左側的某個牧場出發,連接到右側的某個牧場;
人行道連接的兩個牧場的奶牛要能友好相處;
人行道不能在道路中間相交;
每個牧場只能與一條人行道相連。
你需要幫 FJFJ 求出最多能有多少條人行道。

輸入

輸入第一行一個整數 NN

接下來 NN 行,每行一個整數 aia_i,代表道路左側第 ii 個牧場的奶牛品種編號。

接下來 NN 行,每行一個整數 bib_i,代表道路右側第 ii 個牧場的奶牛品種編號。

輸出

輸出最多能畫多少條人行道。

樣例輸入

6
1
2
3
4
5
6
6
5
4
3
2
1

樣例輸出

5

數據範圍

G1N105G:1 \leq N \leq 10^5
P1N1000P:1 \leq N \leq 1000

思路

這道題還是樹狀數組。

我們先記錄bb序列中每個值的位置,然後我們依次枚舉左側的數,然後枚舉能連的點,把這一條路作爲最後一條路,(就是說只能在它的上面建路,其實就是前綴和),看最多能畫多少條,再把這一條路加入樹狀數組中。

最後,我們只需要再輸出前綴和的第nn個(就是最後一個)就可以了。

代碼

#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章