P8023 题解
P8023 题解
题面
思路
首先贪心地想到当前枚举到的两个数那个小就输出哪个,但是我们总会遇到两个数相同的情况,那我们就选择比较后面的第一对不同的数,那个小我们就选哪个,因为这样我们就会更早的选到这个更小的数。
但是如果暴力的话会超时,于是我们可以用哈希优化,求出两个数组的哈希数组,二分两个数组中第一个不同的数,于是时间复杂度就被我们优化成了 \(O((n+m)\log\min(n,m))\)。
注意事项
- 记得在两个数组后面加上一个极大值,这样就可以处理二分之后不同的位置正好到最后一个数。
代码
#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