题目链接:
https://ac.nowcoder.com/acm/contest/881/A
题目大意:
两个长度为 n n n的数组 u u u和 v v v,均由数字 1 − n 1-n 1−n构成,顺序不一定相同。求最大的 q q q,满足以下条件:
- q < = n , n < = 1 e 5 q<=n,n<=1e5 q<=n,n<=1e5
- 对于任意的满足 1 < = l < = r < = q 1<=l<=r<=q 1<=l<=r<=q的 l l l和 r r r,有 R M Q ( u , l , r ) = R M Q ( v , l , r ) RMQ(u,l,r)=RMQ(v,l,r) RMQ(u,l,r)=RMQ(v,l,r)。
- R M Q ( u , l , r ) RMQ(u,l,r) RMQ(u,l,r)的值表示数组 u u u的 [ l , r ] [l,r] [l,r]区间中最小值的索引。
解题思路:
出现数组中大量的
R
M
Q
RMQ
RMQ查询就可以考虑尝试笛卡尔树。笛卡尔树可以简单地获取
R
M
Q
RMQ
RMQ的相关信息,比如已知区间求最小值(或其索引)只要找到这两个区间端点的LCA,已知一个值求以这个值为最小值的所有区间,等等。
此题根据样例尝试手画笛卡尔树,很快发现当
q
q
q符合条件时,两棵笛卡尔树结构是一样的。
因此只要二分答案,check中构造笛卡尔树,构造完判断树是否相同即可。
复杂度
O
(
N
l
o
n
g
N
)
O(NlongN)
O(NlongN)。
AC代码:
#include <stdio.h>
#include <stdlib.h>
int a[100005],b[100005];
typedef struct node{
struct node *l;
struct node *r;
struct node *p;
int val;
}node;
node* create_node(node *p,int val)
{
node *n = (node*)malloc(sizeof(node));
n->l=NULL;n->r=NULL;
n->p = p;n->val = val;
return n;
}
node* tree_insert(node *root,int val)
{
node *now = root;
if (val<now->val)
{
node *new_node = create_node(NULL,val);
new_node->l = root;
return root = new_node;
}
else
{
while(now->val<val)
{
if (now->r==NULL)
{
now->r = create_node(now,val);
return root;
}
now = now->r;
}
node *new_node = create_node(now->p,val);
new_node->l = now;
now->p->r = new_node;
return root;
}
}
bool is_same(node *p1,node *p2)
{
if (p1==NULL&&p2==NULL)
return 1;
else if(p1!=NULL&&p2!=NULL)
return is_same(p1->l,p2->l)&&is_same(p1->r,p2->r);
else
return 0;
}
int check(int mid)
{
int p=1;
node *root_a = create_node(NULL,a[1]);
node *root_b = create_node(NULL,b[1]);
for (p=2;p<=mid;p++)
{
root_a = tree_insert(root_a,a[p]);
root_b = tree_insert(root_b,b[p]);
}
if (is_same(root_a,root_b))return 1;
else return 0;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for (int i=1;i<=n;i++)scanf("%d",&a[i]);
for (int i=1;i<=n;i++)scanf("%d",&b[i]);
int l=2,r=n+1,mid;
while(l<r)
{
mid=(l+r)/2;
if (check(mid))l=mid+1;
else r=mid;
}
printf("%d\n",r-1);
}
}