學長小清新題表之UOJ 180.實驗室外的攻防戰

liuchanglc發表於2020-08-15

學長小清新題表之UOJ 180.實驗室外的攻防戰

題目描述

時針指向午夜十二點,約定的日子——\(2\)\(28\)日終於到來了。隨著一聲槍響,伏特跳蚤國王率領著他的跳蚤大軍們包圍了 \(picks\) 博士所在的實驗室。

當然,\(picks\) 博士不會坐以待斃,他早就率領著他的猴子們在實驗室外修築了許多的堅固防禦工事。

經過跳蚤偵察兵的勘察,跳蚤國王發現 \(picks\) 博士的防禦工事有著 \(n\)
處薄弱點,於是他把他的跳蚤大軍分成了 \(n\) 支小隊,並打算讓它們分別進攻每一個薄弱點。但是因為戰場混亂,這 \(n\) 支小隊的位置被打亂了,重新整隊之後,跳蚤國王發現第 \(i\)個位置的小隊編號為 \(A_i\)(顯然 \(A\)是一個排列)。

經過計算,跳蚤國王發現,讓第 \(i\)個位置的小隊編號為 \(Bi\) 時,他的軍隊可以發揮出最大的戰鬥力(保證 \(B\)也是一個排列)。

跳蚤國王可以發出指令來改變小隊們的排列順序,每一次,他都會報出一個整數 \(i(1≤i<n)\)。如果排在第 \(i\) 個位置的小隊編號大於第 \(i+1\)

個位置的小隊,那麼這兩支小隊會交換順序,否則這一個命令將會被忽略。

現在跳蚤國王希望他的軍隊能夠發揮出最強大的戰鬥力,於是他想要知道是否存在一種指令序列,使得小隊們可以按照排列 \(B\)的方式排列。

但是因為小隊數目實在是太多,跳蚤國王一時間也沒有看出答案。於是他派跳蚤綁架來了你——這附近最著名的民間科學家來幫他計算這個問題的答案。

輸入格式

輸入資料第一行包含一個正整數 \(n\)

接下來兩行每行 \(n\)個正整數,分別描述排列 \(A\) 和排列 \(B\)
輸出格式

對於每組資料,如果存在這樣的指令序列,輸出“YES”,否則輸出“NO”(引號不輸出,請注意大小寫)。

樣例一

input

3
2 3 1
2 1 3

output

YES

explanation

只要報出\(2\),也就是交換第\(2\)個位置和第\(3\)個位置的小隊即可。

樣例二

input

3
2 1 3
3 1 2

output

NO

explanation

注意只有相鄰的滿足前一個數大於後一個數的情況下才可以交換。

樣例三

input

5
4 1 2 5 3
1 2 4 3 5

output

YES

explanation

步驟如下(每次交換的兩個數加粗表示):

4 1 2 5 3

1 4 2 5 3

1 2 4 5 3

1 2 4 3 5

樣例四

input

5
1 5 3 4 2
1 2 4 3 5

output

NO

樣例五

input

8
8 2 7 4 5 3 6 1
2 8 5 7 4 3 6 1

output

NO

樣例六

見樣例資料下載。這組資料符合子任務 \(2\) 的限制與約定。

樣例七

見樣例資料下載。這組資料符合子任務 \(3\) 的限制與約定。

限制與約定

|子任務| 分值 |限制與約定|
|-|-|
|1 |24| \(n≤8\)|
|2| 32 |\(n≤1000\)|
|3 |44| \(n≤100000\)|

對於所有資料,\(1≤n≤100000\),保證輸入的\(A\)\(B\)均為一個排列。

時間限制:\(1s\)

空間限制:\(256MB\)

分析

這一道題有點像

首先我們考慮什麼樣的情況是不存在的

很顯然,在當前佇列中,如果\(i\)\(j\)的左邊,而在目標佇列中\(i\)\(j\)的右邊,並且\(i\)的值要小於\(j\)的值,那麼就是不合法的

因為只有相鄰的滿足前一個數大於後一個數的情況下才可以交換

所以我們按照權值從小到大排好序,同時建立一個線段樹,用在\(b\)序列中的位置當作下標,\(a\)序列中的位置當作權值

每次我們查詢在\(b\)序列中下標大於當前值的元素在\(a\)序列中最小的下標,如果能查詢到,就輸出\(NO\)

否則在最後輸出\(YES\)

程式碼

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
inline int read(){
	register int x=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9'){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0' && ch<='9'){
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return x*f;
}
struct asd{
	int val,wz;
}jl[maxn];
int a[maxn],b[maxn],rk[maxn],rkk[maxn];
bool cmp(asd aa,asd bb){
	return aa.val<bb.val;
}
struct trr{
	int l,r,val;
}tr[maxn];
void push_up(int da){
	tr[da].val=min(tr[da<<1].val,tr[da<<1|1].val);
}
void build(int da,int l,int r){
	tr[da].l=l,tr[da].r=r;
	if(l==r){
		tr[da].val=0x3f3f3f3f;
		return;
	}
	int mids=(l+r)>>1;
	build(da<<1,l,mids);
	build(da<<1|1,mids+1,r);
	push_up(da);
}
void xg(int da,int t,int w){
	if(tr[da].l==tr[da].r){
		tr[da].val=min(tr[da].val,w);
		return;
	}
	int mids=(tr[da].l+tr[da].r)>>1;
	if(t<=mids) xg(da<<1,t,w);
	else xg(da<<1|1,t,w);
	push_up(da);
}
int cx(int da,int l,int r){
	if(tr[da].l>=l && tr[da].r<=r){
		return tr[da].val;
	}
	int ans=0x3f3f3f3f,mids=(tr[da].l+tr[da].r)>>1;
	if(l<=mids) ans=min(ans,cx(da<<1,l,r));
	if(r>mids) ans=min(ans,cx(da<<1|1,l,r));
	return ans;
}
int main(){
	int n;
	n=read();
	build(1,1,n);
	for(register int i=1;i<=n;i++){
		a[i]=read();
		rkk[a[i]]=i;
	}
	for(register int i=1;i<=n;i++){
		b[i]=read();
		rk[b[i]]=i;
	}
	for(register int i=1;i<=n;i++){
		jl[i].val=a[i];
		jl[i].wz=rk[a[i]];
	}
	sort(jl+1,jl+1+n,cmp);
	for(register int i=1;i<=n;i++){
		int now=cx(1,jl[i].wz,n);
		if(now<rkk[jl[i].val]){
			printf("NO\n");
			return 0;
		}
		xg(1,jl[i].wz,rkk[jl[i].val]);
	}
	printf("YES\n");
	return 0;
}

相關文章