P8023 题解

P8023 题解

题面

原题传送门

思路

首先贪心地想到当前枚举到的两个数那个小就输出哪个,但是我们总会遇到两个数相同的情况,那我们就选择比较后面的第一对不同的数,那个小我们就选哪个,因为这样我们就会更早的选到这个更小的数。

但是如果暴力的话会超时,于是我们可以用哈希优化,求出两个数组的哈希数组,二分两个数组中第一个不同的数,于是时间复杂度就被我们优化成了 \(O((n+m)\log\min(n,m))\)

注意事项

  1. 记得在两个数组后面加上一个极大值,这样就可以处理二分之后不同的位置正好到最后一个数。

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
//#define gc getchar
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#define ll long long
using namespace std;
const int MN=2e5+5,base=1e5+43,mod=1e9+403;
ll n,m,pa,pb,a[MN],b[MN],ha[MN],hb[MN],pw[MN]={1};
char buf[1<<23],*p1=buf,*p2=buf;
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=gc();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=gc();}return x*f;}
ll gsa(ll l, ll r){return (ha[r]-ha[l-1]*pw[r-l+1]%mod+mod)%mod;}
ll gsb(ll l, ll r){return (hb[r]-hb[l-1]*pw[r-l+1]%mod+mod)%mod;}
bool pd(){
    ll l=1,r=min(n-pa,m-pb)+2;
    while(l<r){
        ll mid=l+r>>1;
        if(gsa(pa,pa+mid-1)==gsb(pb,pb+mid-1)) l=mid+1;
        else r=mid;
    }
    return a[pa+l-1]<b[pb+l-1];
}
int main(){
    //ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    n=read();pa=1;a[n+1]=1e18;
    for(int i=1; i<=n; i++) a[i]=read(),ha[i]=(ha[i-1]*base+a[i])%mod;
    m=read();pb=1;b[m+1]=1e18;
    for(int i=1; i<=m; i++) b[i]=read(),hb[i]=(hb[i-1]*base+b[i])%mod;
    for(int i=1; i<MN; i++) pw[i]=pw[i-1]*base%mod;
    while(pa<=n||pb<=m){
        if(pb>m||pd()) write(a[pa++]),putchar(' ');
        else write(b[pb++]),putchar(' ');
    }
    return 0;
}//250727
posted @ 2025-07-27 23:47  naroto2022  阅读(10)  评论(0)    收藏  举报