2019牛客暑期多校训练营(第一场) A Equivalent Prefixes

题意:给你两个数组a,b,大小为n,让你寻找一个数p (1<= p <= n) ,使之在 1~p 任意一个区间中a,b数组的最小值下标相同。
分析:

方法一:单调栈维护两个数组内元素单调递增,当栈内元素 的个数不相同时,退出循环(本质是方法二)。

方法二:找每个点的左边的比它小的数的所在的位置,然后如果两点的左边比它小的数的位置不同,那么肯定这一位就不能取了。

方法三:二分+st表,在二分p的过程中,我们这样来判断结尾位置mid是否合法:询问1~mid 区间两个数组中的最小值下标是否一致,如果不一致直接返回false,否则 以最小值下标minid为分界点递归处理1~minid,minid+1~mid。

方法四:笛卡尔树。

代码一(方法一):

#include
using namespace std;
const int N=1e5+9;
 
int a[N],b[N];
int u[N],v[N];
 
int main(){
    int n;
    while(cin>>n){
        for(int i=1;i<=n;i++){
            scanf("%d",a+i);
            u[i]=i-1;
            while(a[u[i]]>a[i])u[i]=u[u[i]];
        }
        for(int i=1;i<=n;i++){
            scanf("%d",b+i);
            v[i]=i-1;
            while(b[v[i]]>b[i])v[i]=v[v[i]];
        }
        v[n+1]=u[n+1]+1;
        for(int i=1;i

代码二(方法二):

#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
stack sta1,sta2;
int main(){
    int n;
    while(cin >> n){
        int a[100005],b[100005];
        for(int i = 1; i <= n; i++) cin >> a[i];
        for(int i = 1; i <= n; i++) cin >> b[i];
        int k = 1;
        while(!sta1.empty()) sta1.pop();
        while(!sta2.empty()) sta2.pop();
        sta1.push(a[1]);
        sta2.push(b[1]);
        while(k < n){
            while(!sta1.empty() && sta1.top() > a[k+1])
                sta1.pop();
            if(sta1.empty() || a[k+1]>sta1.top()) sta1.push(a[k+1]);
            while(!sta2.empty() && sta2.top() > b[k+1]) sta2.pop();
            if(sta2.empty() || b[k+1] > sta2.top()) sta2.push(b[k+1]);
            if(sta1.size() != sta2.size()) break;
            k++;
        }
        cout << k << endl;
    }
    return 0;
}

代码三(方法三):

#include
const int N = 1e5+5;
using namespace std;
int n,a[N],b[N],dp[N][20],dp2[N][20];

void init() {
    for(int i=0;i=r) return 1;
    int x=idxa(l,r),y=idxb(l,r);
    if(x!=y) return 0;
    else return ck(l,x-1)&&(ck(x+1,r));
}

void sv() {
    int l=0,r=n-1,ans=0;
    while(l<=r) {
        int m=(l+r)/2;
        if(ck(0,m)) l=m+1,ans=m;
        else r=m-1;
    }
    printf("%d\n",ans+1);
}

int main(){
    while(scanf("%d",&n)!=EOF){
        for(int i=0;iv之间找区间最小值,
                                    //加等号,取小标小的
    //1<

 

你可能感兴趣的:(st表,单调栈)