ARC 187 C/D

C

upd: 我的证明写错了一点,修复了。

upd: 我的脑子错了一点,修复了。

首先扔出一个结论,如果 Q 中没有 1,那么答案是 2k,其中 k=i=2n[Qi=max(Q1i)]。考虑证明。

Qi=max(Q1i) 的位置(包含 i=1)是 a1ak+1。那么设 fi1ai 的答案,显然 f1=1。考虑 Qai 放哪。我们发现可以插在前面一个前缀最大值 aj 的正后方,而 aj+1ai 是啥都固定了,并且 1ajfj。还有一种情况是插在最前面。那么得出 fi=j=1i1fj+1,则 f1=1,f2=2,f3=1+2+1=4,f4=1+2+4+1=8,,fk+1=2k

因此设 fi,j 为前 i 位,现在 maxj 的答案即可。为了方便,设 Q0=0,最后答案是 fn,n2

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 5e3+3;
const ll mod = 998244353;
const ll i2 = (mod+1)/2;

int n,m,a[N],vis[N],t[N];
ll f[N],s[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		if (a[i]!=-1) vis[a[i]]=1;
	}
	for (int i=1; i<=n; i++){
		t[i]=t[i-1]+(vis[i]==0);
	}
	f[0]=1;
	for (int i=1,c=0; i<=n; i++){
		if (a[i]!=-1){
			for (int j=1; j<=a[i]; j++){
				f[j]=(f[j]+f[j-1])%mod;
				f[j-1]=0;
			}
			f[a[i]]=(f[a[i]]+f[a[i]])%mod;
		}
		else{
			s[0]=f[0];
			for (int j=1; j<=n; j++){
				s[j]=(f[j]+s[j-1])%mod;
			}
			f[0]=0;
			for (int j=1; j<=n; j++){
				f[j]=(f[j]*(t[j]-c)%mod+s[j-1]*2*(!vis[j]))%mod;
			}
			c++;
		}
		if (i!=n) f[n]=0;
	}
	cout<<f[n]*i2%mod<<"\n";
	return 0;
}

D

D<<C。

fi 为最小是 i 的最小最大值。那么,当加入 (a,b) 的时候,

  • iafi=max(fi,a)
  • a<ibfi=max(fi,b)
  • i>bfi=

这个直接用线段树维护即可。

#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 5e5+5;

int n,m,a[N],b[N],lsh[N*2];
int mn[N<<3],ml[N<<3],mr[N<<3],tg[N<<3];

void pu(int k){
	mn[k]=min(mn[k<<1],mn[k<<1|1]);
	ml[k]=ml[k<<1],mr[k]=mr[k<<1|1];
}

void bd(int k,int l,int r){
	ml[k]=lsh[l],mr[k]=lsh[r];
	if (l==r) return;
	int mid=l+r>>1;
	bd(k<<1,l,mid);
	bd(k<<1|1,mid+1,r);
}

void F(int k,int id,int z){
	ml[k]=mr[k]=tg[k]=z,mn[k]=z-lsh[id];
}

void pd(int k,int l,int r){
	if (tg[k]){
		int mid=l+r>>1;
		F(k<<1,mid,tg[k]);
		F(k<<1|1,r,tg[k]);
		tg[k]=0;
	}
}

void upd(int k,int l,int r,int ql,int qr,int v){
	if (r<ql || l>qr || ql>qr) return;
	if (v<=ml[k]) return;
	if (ql<=l && r<=qr && v>=mr[k]){
		F(k,r,v);
		return;
	}
	pd(k,l,r);
	int mid=l+r>>1;
	upd(k<<1,l,mid,ql,qr,v);
	upd(k<<1|1,mid+1,r,ql,qr,v);
	pu(k);
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		lsh[++m]=a[i];
	}
	for (int i=1; i<=n; i++){
		cin>>b[i];
		lsh[++m]=b[i];
	}
	sort(lsh+1,lsh+1+m);
	m=unique(lsh+1,lsh+1+m)-lsh;
	bd(1,1,m);
	for (int i=1; i<=n; i++){
		int A=lower_bound(lsh+1,lsh+1+m,a[i])-lsh;
		int B=lower_bound(lsh+1,lsh+1+m,b[i])-lsh;
		if (A>B) swap(A,B),swap(a[i],b[i]);
		upd(1,1,m,1,A,a[i]);
		upd(1,1,m,A+1,B,b[i]);
		upd(1,1,m,B+1,m,2e9);
		cout<<mn[1]<<"\n";
	}
	return 0;
}
posted @   SFlyer  阅读(67)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· 一文读懂知识蒸馏
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示