专栏文章

题解:CF2048F Kevin and Math Class

CF2048F题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minl12mg
此快照首次捕获于
2025/12/02 04:08
3 个月前
此快照最后确认于
2025/12/02 04:08
3 个月前
查看原文
区间最值操作最优解,最大支配区间,考虑笛卡尔树。
注意到操作数不超过 logV\log V 次,记 dpu,idp_{u,i} 表示 uu 的子树内操作 ii 次的最大值最小是多少。
暴力背包合并即可,时间复杂度 O(nlog2V)O(n\log^2 V)
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read(){
	ll x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}
bool mbs;
const int maxn=2e5+20;
ll T,n,a[maxn],b[maxn],sta[maxn],top,ls[maxn],rs[maxn],dp[maxn][70],st[maxn][30],lg[maxn];
inline ll ask(int l,int r){
	int k=lg[r-l+1];
	return max(st[l][k],st[r-(1<<k)+1][k]);
}
void dfs(int u,int l,int r){
	if(!u) return;
	dfs(ls[u],l,u-1),dfs(rs[u],u+1,r);
	dp[u][0]=ask(l,r);
	for(int i=1;i<=65;i++) dp[u][i]=dp[u][0];
	for(int i=1;i<=65;i++) for(int j=0;j<=i;j++) dp[u][i]=min(dp[u][i],max({dp[ls[u]][j],dp[rs[u]][i-j],a[u]}));
	for(int i=1;i<=65;i++) dp[u][i]=min(dp[u][i],(dp[u][i-1]+b[u]-1)/b[u]);
}
inline void solve(){
	n=read();top=0;
	for(int i=1;i<=n;i++) a[i]=read(),ls[i]=rs[i]=sta[i]=0,st[i][0]=a[i];
	for(int i=1;i<=20;i++) for(int j=1;j+(1<<i)-1<=n;j++) st[j][i]=max(st[j][i-1],st[j+(1<<(i-1))][i-1]);
	for(int i=1;i<=n;i++){
		b[i]=read();int k=top;
		while(k&&b[sta[k]]>b[i]) k--;
		if(k) rs[sta[k]]=i;
		if(k!=top) ls[i]=sta[k+1];
		sta[++k]=i,top=k;
	} 
	while(top>1) rs[sta[top-1]]=sta[top],top--;
	dfs(sta[1],1,n);
	for(int i=0;i<=65;i++) if(dp[sta[1]][i]==1) return printf("%d\n",i),void();
}
bool mbt;
int main(){
//	cerr<<(&mbs-&mbt)/1024.0/1024.0<<endl;
	T=read();
	for(int i=2;i<=200000;i++) lg[i]=lg[i>>1]+1; 
	while(T--) solve();
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...