P9870 [NOIP2023] 双序列拓展

ooliver OI

钦定 Y_1">X1>Y1X_1>Y_1,不难发现必须满足 Y_{max},\ X_{min}>Y_{min}">Xmax>Ymax, Xmin>YminX_{max}>Y_{max},\ X_{min}>Y_{min},

再看特殊性质,不难发现直接递归求解即可,每次检查是否能达到当前的 XmaxX_{max} 或 YminY_{min}。

这里的 XmaxX_{max} 和 YminY_{min} 将原序列分成了两个部分,而两个部分正好是特殊性质,所以分两次递归即可。

代码:

#include
using namespace std;

const int N=5e5+5;
int n,m,q;
int x[N],y[N],a[N],b[N],ta[N],tb[N];
int pma[N],pmi[N],pmb[N],pmj[N];
int sma[N],smi[N],smb[N],smj[N];

void init(){
    pma[1]=pmi[1]=1;
    for(int i=2;ia[pma[i-1]]?i:pma[i-1];
    }
    pmb[1]=pmj[1]=1;
    for(int i=2;ib[pmb[i-1]]?i:pmb[i-1];
    }
    sma[n]=smi[n]=n;
    for(int i=n-1;i>=1;i--){
        smi[i]=a[i]a[sma[i+1]]?i:sma[i+1];
    }
    smb[m]=smj[m]=m;
    for(int i=m-1;i>=1;i--){
        smj[i]=b[i]b[smb[i+1]]?i:smb[i+1];
    }
}

bool chk1(int i,int j){
    if(i==1||j==1) return 1;
    if(a[pmi[i-1]]a[pma[i-1]]) return chk1(i,pmb[j-1]);
    return 0;
}

bool chk2(int i,int j){
    if(i==n||j==m) return 1;
    if(a[smi[i+1]]a[sma[i+1]]) return chk2(i,smb[j+1]);
    return 0;
}

bool sol(){
    if(a[1]>=b[1]) return 0;
    init();
    int ma=pma[n],mj=pmj[m];
    if(a[pmi[n]]>=b[pmj[m]]||b[pmb[m]]
`#include
using namespace std;

const int N=5e5+5;
int n,m,q;
int x[N],y[N],a[N],b[N],ta[N],tb[N];
int pma[N],pmi[N],pmb[N],pmj[N];
int sma[N],smi[N],smb[N],smj[N];

void init(){
    pma[1]=pmi[1]=1;
    for(int i=2;i
        pmi[i]=a[i]a[pmi[i-1]]?i:pmi[i-1];
        pma[i]=a[i]>a[pma[i-1]]?i:pma[i-1];
    }
    pmb[1]=pmj[1]=1;
    for(int i=2;i
        pmj[i]=b[i]b[pmj[i-1]]?i:pmj[i-1];
        pmb[i]=b[i]>b[pmb[i-1]]?i:pmb[i-1];
    }
    sma[n]=smi[n]=n;
    for(int i=n-1;i>=1;i--){
        smi[i]=a[i]a[smi[i+1]]?i:smi[i+1];
        sma[i]=a[i]>a[sma[i+1]]?i:sma[i+1];
    }
    smb[m]=smj[m]=m;
    for(int i=m-1;i>=1;i--){
        smj[i]=b[i]b[smj[i+1]]?i:smj[i+1];
        smb[i]=b[i]>b[smb[i+1]]?i:smb[i+1];
    }
}

bool chk1(int i,int j){
    if(i==1||j==1) return 1;
    if(a[pmi[i-1]]b[pmj[j-1]]) return chk1(pmi[i-1],j);
    if(b[pmb[j-1]]>a[pma[i-1]]) return chk1(i,pmb[j-1]);
    return 0;
}

bool chk2(int i,int j){
    if(i==n||j==m) return 1;
    if(a[smi[i+1]]b[smj[j+1]]) return chk2(smi[i+1],j);
    if(b[smb[j+1]]>a[sma[i+1]]) return chk2(i,smb[j+1]);
    return 0;
}

bool sol(){
    if(a[1]>=b[1]) return 0;
    init();
    int ma=pma[n],mj=pmj[m];
    if(a[pmi[n]]>=b[pmj[m]]||b[pmb[m]]a[pma[n]]) return 0;
    return chk1(pmi[n],pmb[m])&&chk2(pmi[n],pmb[m]);
}

int main(){
    scanf("%*d%d%d%d",&n,&m,&q);
    for(int i=1;iscanf("%d",&x[i]);
    for(int i=1;iscanf("%d",&y[i]);
    for(int i=1;ita[i]=x[i];
    for(int i=1;itb[i]=y[i];
    for(int i=1;ia[i]=ta[i];
    for(int i=1;ib[i]=tb[i];
    bool res1=sol();
    swap(n,m);
    for(int i=1;ia[i]=tb[i];
    for(int i=1;ib[i]=ta[i];
    bool res2=sol();
    swap(n,m);
    putchar(res1||res2?'1':'0');
    while(q--){
        for(int i=1;ita[i]=x[i];
        for(int i=1;itb[i]=y[i];
        int kx,ky;
        scanf("%d%d",&kx,&ky);
        while(kx--){
            int p,v;
            scanf("%d%d",&p,&v);
            ta[p]=v;
        }
        while(ky--){
            int p,v;
            scanf("%d%d",&p,&v);
            tb[p]=v;
        }
        for(int i=1;ia[i]=ta[i];
        for(int i=1;ib[i]=tb[i];
        bool res1=sol();
        swap(n,m);
        for(int i=1;ia[i]=tb[i];
        for(int i=1;ib[i]=ta[i];
        bool res2=sol();
        swap(n,m);
        putchar(res1||res2?'1':'0');
    }
    return 0;
}`