题解 CF2053D Refined Product Optimality
复活后的第一篇题解和比赛。
感觉这是一个很有意思的题。
题意
有两个长度为
有
时, 。 时, 。
设
由于答案可能很大,所以对
分析
不难证明,最大值即为将
简单证明一下,假设
于是就可以在
修改只会修改一个,也只会增加
修改的时候如果要调整序列来维持单调性是一件很麻烦的事情。假设我们修改的是
于是求出这个位置后,可以撤销该位置对答案原有的贡献,乘上该位置的逆元,然后修改后再将贡献加入进去即可。
以上操作就可以用二分和快速幂解决,修改
总体时间复杂度为
代码
//the code is from chenjh
#include<bits/stdc++.h>
#define MAXN 200002
using namespace std;
typedef long long LL;
constexpr int mod=998244353;
int n,q;
int qpow(int a,int b=mod-2){
int ret=1;
for(;b;b>>=1,a=(LL)a*a%mod)if(b&1)ret=(LL)ret*a%mod;
return ret%mod;
}
int a[MAXN],b[MAXN],c[MAXN],d[MAXN];//c,d 序列表示排序后的 a,b 序列。
void solve(){
cin>>n>>q;
for(int i=1;i<=n;i++) cin>>a[i],c[i]=a[i];
for(int i=1;i<=n;i++) cin>>b[i],d[i]=b[i];
sort(c+1,c+n+1),sort(d+1,d+n+1);
int ans=1;
for(int i=1;i<=n;i++) ans=(LL)ans*min(c[i],d[i])%mod;
cout<<ans<<' ';
for(int o,x,p;q--;){
cin>>o>>x;
p=0;
if(o==1)
p=upper_bound(c+1,c+n+1,a[x])-c-1,//找到第一个大于 a_x 的位置的前一个,即最后一个等于 a_x 的位置。
ans=(LL)ans*qpow(min(c[p],d[p]))%mod,//除以这个数,即乘这个数的逆元。
++a[x],++c[p];//对这些位置进行修改。
else if(o==2)
p=upper_bound(d+1,d+n+1,b[x])-d-1,//b 序列同理。
ans=(LL)ans*qpow(min(c[p],d[p]))%mod,
++b[x],++d[p];
ans=(LL)ans*min(c[p],d[p])%mod;//乘上修改后这个位置的贡献。
cout<<ans<<' ';
}
cout<<'\n';
}
int main(){
ios::sync_with_stdio(false),cin.tie(nullptr);
int T;cin>>T;
while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现