P9870题解
P9870 [NOIP2023] 双序列拓展
题解
T3 双序列拓展(expand)
考察:dp、人类智慧(
部分分启示正解。
的
将原题目转化为这样:两个指针分别指着两个序列,每次将任意至少一个指针向后移一个位置,并使每时每刻都满足两个指针所指的位置有单调的偏序关系。
所谓单调的偏序关系可以用第一个位置来判断,在下文我们只考虑
我们考虑 dp:记
的特殊性质
我们考虑构造 01 矩阵
其实我们不会向右下走,因为可以证明不存在
1 0
0 1
这样的矩阵,但对正解没啥作用,所以我就没管了。
由于性质保证,我们发现最后一列与最后一行都是
对于
实现的话预处理前缀
其实
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
int s=0,m=0;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return m?-s:s;
}
int cc,n,m,q,c[500005],d[500005],a[500005],b[500005],pax[500005],pan[500005],sax[500005],san[500005],pbx[500005],pbn[500005],sbx[500005],sbn[500005];
bool calc1(int x,int y) {
if(x==1||y==1) return 1;
int ax=pax[x-1],an=pan[x-1],bx=pbx[y-1],bn=pbn[y-1];
if(a[an]<b[bn]) return calc1(an,y);
if(b[bx]>a[ax]) return calc1(x,bx);
return 0;
}
bool calc2(int x,int y) {
if(x==n||y==m) return 1;
int ax=sax[x+1],an=san[x+1],bx=sbx[y+1],bn=sbn[y+1];
if(a[an]<b[bn]) return calc2(an,y);
if(b[bx]>a[ax]) return calc2(x,bx);
return 0;
}
bool check() {
if(a[1]>b[1]) {
for(int i=1;i<=n;i++) a[i]*=-1;
for(int i=1;i<=m;i++) b[i]*=-1;
}
pax[1]=1,pan[1]=1;
for(int i=2;i<=n;i++)
pax[i]=(a[pax[i-1]]>a[i]?pax[i-1]:i),
pan[i]=(a[pan[i-1]]<a[i]?pan[i-1]:i);
pbx[1]=1,pbn[1]=1;
for(int i=2;i<=m;i++)
pbx[i]=(b[pbx[i-1]]>b[i]?pbx[i-1]:i),
pbn[i]=(b[pbn[i-1]]<b[i]?pbn[i-1]:i);
sax[n]=n,san[n]=n;
for(int i=n-1;i>=1;i--)
sax[i]=(a[sax[i+1]]>a[i]?sax[i+1]:i),
san[i]=(a[san[i+1]]<a[i]?san[i+1]:i);
sbx[m]=m,sbn[m]=m;
for(int i=m-1;i>=1;i--)
sbx[i]=(b[sbx[i+1]]>b[i]?sbx[i+1]:i),
sbn[i]=(b[sbn[i+1]]<b[i]?sbn[i+1]:i);
int ax=pax[n],an=pan[n],bx=pbx[m],bn=pbn[m];
if(a[an]>=b[bn]) return 0;
if(b[bx]<=a[ax]) return 0;
return calc1(an,bx)&calc2(an,bx);
}
signed main() {
cin>>cc>>n>>m>>q;
for(int i=1;i<=n;i++)
a[i]=c[i]=rd();
for(int i=1;i<=m;i++)
b[i]=d[i]=rd();
cout<<check();
while(q--) {
for(int i=1;i<=n;i++) a[i]=c[i];
for(int i=1;i<=m;i++) b[i]=d[i];
int k1=rd(),k2=rd();
for(int i=1;i<=k1;i++) {
int p=rd(),v=rd();
a[p]=v;
}
for(int i=1;i<=k2;i++) {
int p=rd(),v=rd();
b[p]=v;
}
cout<<check();
}
return 0;
}
时间复杂度
本文来自博客园,作者:operator,转载请注明原文链接:https://www.cnblogs.com/operator-/p/17974779 ♪(^∀^●)ノシ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!