Description
在2050年机器人战争爆发,聪明的机器猫为了帮助大雄打赢这场战 争,从自己口袋里掏出了机器人战棋,每一个战棋都可以成为一名战士,哆啦A梦决定给他们整整队,哆啦A梦发现第 i 个位置的战士编号为 Ai(显然 A 是一个排列)。经过计算,哆啦A梦发现,让第 i 个位置的战士编号为 Bi 时,他的军队可以发挥出最大的战斗力(保证 B 也是一个排列)。
哆啦A梦可以发出指令来改变战士们的排列顺序,每一次,他都会报出一个整数 i(1≤i<n)。如果排在第 i 个位置的战士编号大于第 i+1 个位置的战士,那么这两个战士会交换顺序,否则这一个命令将会被忽略。
现在哆啦A梦希望他的军队能够发挥出最强大的战斗力,于是他想要知道是否存在一种指令序列,使得战士们可以按照排列 B 的方式排列。
但是因为战士数目实在是太多,哆啦A梦一时间也没有看出答案。于是他用时间机器带来了你——21世纪最著名的民间科学家来帮他计算这个问题的答案。
Input
输入数据第一行包含一个正整数 n(n<=100000)。
接下来两行每行 n 个正整数,分别描述排列 A和排列 B。
Output
对于每组数据,如果存在这样的指令序列,输出“YES”,否则输出“NO”(引号不输出,请注意大小写)。
Sample Input
3 2 3 1 2 1 3 3 2 1 3 3 1 2
Sample Output
YES NO 思路:这道题是山科第三届校赛的H题,我们队过的最后一道题,由于太弱,想了大概一个小时左右才初步有了思路就是先建一棵max的线段树,数组a和b分别记录交换之前和交换之后数值的下标然后从大到小循环,每次判断该数值是否向右移动(或者不移动),如果成立就询问线段树初始位置在该元素右边的值移动后所在的最左端的位置。当前数值移动后的位置必须小于查询的结果。然后每个值都更新线段树,将初始位置的值更新为交换之后的位置。然后同理从小到大循环,每次判断向左移动,询问最右端的位置就好了
/* *********************************************** Author :devil Created Time :2016/4/26 13:11:52 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; const int N=100005; int n,a[N],b[N],tree[N<<2]; void build1(int node,int l,int r) { if(l==r) { tree[node]=N; return ; } int m=(l+r)>>1; build1(node<<1,l,m); build1(node<<1|1,m+1,r); tree[node]=min(tree[node<<1],tree[node<<1|1]); } void update1(int node,int l,int r,int p) { if(l==r) { tree[node]=b[p]; return ; } int m=(l+r)>>1; if(a[p]<=m) update1(node<<1,l,m,p); else update1(node<<1|1,m+1,r,p); tree[node]=min(tree[node<<1],tree[node<<1|1]); } int query1(int node,int l,int r,int p) { if(l>=p) return tree[node]; int m=(l+r)>>1,ans; ans=query1(node<<1|1,m+1,r,p); if(p<=m) ans=min(ans,query1(node<<1,l,m,p)); return ans; } void build2(int node,int l,int r) { if(l==r) { tree[node]=0; return ; } int m=(l+r)>>1; build2(node<<1,l,m); build2(node<<1|1,m+1,r); tree[node]=max(tree[node<<1],tree[node<<1|1]); } void update2(int node,int l,int r,int p) { if(l==r) { tree[node]=b[p]; return ; } int m=(l+r)>>1; if(a[p]<=m) update2(node<<1,l,m,p); else update2(node<<1|1,m+1,r,p); tree[node]=max(tree[node<<1],tree[node<<1|1]); } int query2(int node,int l,int r,int p) { if(r<=p) return tree[node]; int m=(l+r)>>1,ans; ans=query2(node<<1,l,m,p); if(p>m) ans=max(ans,query2(node<<1|1,m+1,r,p)); return ans; } int main() { //freopen("in.txt","r",stdin); while(~scanf("%d",&n)) { int x,flag=1; for(int i=1; i<=n; i++) { scanf("%d",&x); a[x]=i; } for(int i=1; i<=n; i++) { scanf("%d",&x); b[x]=i; } build1(1,1,n); for(int i=n; i>0; i--) { if(a[i]<=b[i]&&b[i]>query1(1,1,n,a[i])) { flag=0; break; } update1(1,1,n,i); } if(!flag) { printf("NO\n"); continue; } build2(1,1,n); for(int i=1; i<=n; i++) { if(a[i]>=b[i]&&b[i]<query2(1,1,n,a[i])) { flag=0; break; } update2(1,1,n,i); } if(!flag) printf("NO\n"); else printf("YES\n"); } return 0; }
时间: 2024-10-01 22:12:13