Educational Codeforces Round 67 (Rated for Div. 2)链接
D. Subarray Sorting
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an array ?1,?2,…,??a1,a2,…,an and an array ?1,?2,…,??b1,b2,…,bn.
For one operation you can sort in non-decreasing order any subarray ?[?…?]a[l…r] of the array ?a.
For example, if ?=[4,2,2,1,3,1]a=[4,2,2,1,3,1] and you choose subbarray ?[2…5]a[2…5], then the array turns into [4,1,2,2,3,1][4,1,2,2,3,1].
You are asked to determine whether it is possible to obtain the array ?b by applying this operation any number of times (possibly zero) to the array ?a.
Input
The first line contains one integer ?t (1≤?≤3⋅1051≤t≤3⋅105) — the number of queries.
The first line of each query contains one integer ?n (1≤?≤3⋅1051≤n≤3⋅105).
The second line of each query contains ?n integers ?1,?2,…,??a1,a2,…,an (1≤??≤?1≤ai≤n).
The third line of each query contains ?n integers ?1,?2,…,??b1,b2,…,bn (1≤??≤?1≤bi≤n).
It is guaranteed that ∑?≤3⋅105∑n≤3⋅105 over all queries in a test.
Output
For each query print YES (in any letter case) if it is possible to obtain an array ?b and NO (in any letter case) otherwise.
这道题的题意是让我们求,我们对几次这样的[l, r]的区间按生序排序,然后问,第一段区间经过这样的变化是否可以变成第二段区间?
我们用样例来举例说明:
7
1 7 1 4 4 5 6
1 1 4 4 5 7 6
这组数据,想从第一排变成第二排的,我们是不是可以把「1 7 1 4 4 5」排个序就可以了?然后就是最终的答案了。
那么怎么去解释这样的数据呢?首先看第二排的数据的第一个“1”出现在第一排的第一位上,是可以直接不动的,那么就用掉它了;然后,往下,第二个“1”在位置三上,前面没有比它小的数,又可以用掉了(1、7换位了);然后是“4”,第一次出现“4”实在位置四上面,前面也没有比它小的数了,也是可以的,直接去与7换位即可;再往后是第二个数,在第一排中对应的第五位置是可以找到的;然后是“5”,在它的前面也是没有比它小的数了,也可以这样做到;……我们一次类推,发现整个数据都是可以推完的。
那么,再看一组“NO”的数据:
3
1 2 3
3 2 1
第一个是“3”,对应的第一排中,前面有“1”和“2”,那么我没没发换“3”,若取“3”就一定会取“1”,我们根据这样的关系,有了线段树维护前缀(1~qr)的最小值,并且不断更新的操作。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
#define MP3(a, b, c) MP(MP(a, b), c)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 3e5 + 7;
int N, a[maxN], b[maxN], num[maxN], tree[maxN<<2];
inline void pushup(int rt) { tree[rt] = min(tree[lsn], tree[rsn]); }
inline void buildTree(int rt, int l, int r)
{
if(l == r)
{
tree[rt] = a[l];
return;
}
int mid = HalF;
buildTree(Lson);
buildTree(Rson);
pushup(rt);
}
int query(int rt, int l, int r, int ql, int qr)
{
if(ql <= l && qr >= r) return tree[rt];
int mid = HalF;
if(qr <= mid) return query(QL);
else if(ql > mid) return query(QR);
else return min(query(QL), query(QR));
}
inline void update(int rt, int l, int r, int qx)
{
if(l == r) { tree[rt] = INF; return; }
int mid = HalF;
if(qx <= mid) update(Lson, qx);
else update(Rson, qx);
pushup(rt);
}
queue<int> vt[maxN];
inline void init()
{
for(int i=1; i<=N; i++) num[i] = 0;
for(int i=1; i<=N; i++) { while(!vt[i].empty()) vt[i].pop(); }
}
int main()
{
int T; scanf("%d", &T);
while(T--)
{
scanf("%d", &N);
init();
for(int i=1; i<=N; i++) { scanf("%d", &a[i]); num[a[i]]++; }
for(int i=1; i<=N; i++) { scanf("%d", &b[i]); num[b[i]]--; }
bool flag = true;
for(int i=1; i<=N; i++)
{
if(num[i] != 0)
{
printf("NO\n");
flag = false;
break;
}
}
if(!flag) continue;
buildTree(1, 1, N);
for(int i=1; i<=N; i++) vt[a[i]].push(i);
for(int i=1, tmp; i<=N; i++)
{
tmp = query(1, 1, N, 1, vt[b[i]].front());
if(tmp < b[i]) { flag = false; break; }
update(1, 1, N, vt[b[i]].front());
vt[b[i]].pop();
}
printf(flag ? "YES\n" : "NO\n");
}
return 0;
}
/*
1
8
1 3 2 6 5 4 7 4
1 2 3 5 6 4 4 7
ans:YES
*/