A.Equivalent Prefixes
传送门:https://ac.nowcoder.com/acm/contest/881/A
题意:给你两个序列 A、B,两个区间相等的条件是区间内任意一个子区间的当前子区间的最小值的坐标相等,问你两个序列的1~p区间相等,求最大的p是多少
题解:二分+分治+rmq
因为区间p的取值不好取,于是我们二分答案
check怎么check,因为我们的区间内每一个子区间都需要检查到,那么我们就需要从大区间检查到小区间,所以,很容易想到分治,递归到子区间去,再进行检查,检查的时候去找到区间最小值,为了检查的时候时间复杂度尽可能的小,我们需要需要用一种数据结构去得到区间最小值,这里使用了rmq预处理 O1查询
代码
#include <set>
#include <map>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********
")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]
"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]
"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]
"
const int maxn = 100000 + 5;
const int INF = 0x3f3f3f3f;
int a[maxn], b[maxn];
int pos1[maxn], pos2[maxn];
int st1[maxn][20];
int n;
void rmq_init1() {
for (int i = 1; i <= n; i++) {
st1[i][0] = a[i];
}
int l = 2;
for (int i = 1; l <= n; i++) {
for (int j = 1; j + l / 2 <= n; j++) {
st1[j][i] = min(st1[j][i - 1], st1[j + l / 2][i - 1]);
}
l <<= 1;
}
}
int ask_min1(int i, int j) {
int k = int(log(j - i + 1.0) / log(2.0));
return min(st1[i][k], st1[j - (1 << k) + 1][k]);
}
int st2[maxn][20];
void rmq_init2() {
for (int i = 1; i <= n; i++) {
st2[i][0] = b[i];
}
int l = 2;
for (int i = 1; l <= n; i++) {
for (int j = 1; j + l / 2 <= n; j++) {
st2[j][i] = min(st2[j][i - 1], st2[j + l / 2][i - 1]);
}
l <<= 1;
}
}
int ask_min2(int i, int j) {
int k = int(log(j - i + 1.0) / log(2.0));
return min(st2[i][k], st2[j - (1 << k) + 1][k]);
}
bool check(int l, int r) {
if(l >= r) return true;
int min1 = ask_min1(l, r);
int min2 = ask_min2(l, r);
int p1 = pos1[min1];
int p2 = pos2[min2];
if(p1 == p2) {
return check(l, p1 - 1) && check(p1 + 1, r);
} else {
return false;
}
}
int main() {
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
pos1[a[i]] = i;
}
for(int i = 1; i <= n; i++) {
scanf("%d", &b[i]);
pos2[b[i]] = i;
}
rmq_init1();
rmq_init2();
int l = 1, r = n;
int ans = 1;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(1, mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
printf("%d
", ans);
}
return 0;
}