为啥我不在的场都是上分场。(CF2110F)
CF 的套路是这样的,对于这种常规手段很难搞的题直接找性质,然后就变成了纸老虎。为啥我不在的场都是上分场。
写在前面,整道题其实就在围绕一个看似显然的关键结论,对于任意的 \(x,y\) 满足 \(x<y\),我们有 \(x\le f(x,y)\le y\),且 \(f(x,y)=y\) 当且仅当 \(2x>y\)。
我们考虑当前要插入 \(a_i\),此时 \(a_1\) 至 \(a_{i-1}\) 的最大值为 \(mx\),严格次大值(代码中无需实现,仅用于下文证明)为 \(mx'\),当前答案为 \(ans\)。
首先如果 \(a_i=mx\) 那么等于不存在,下文默认 \(a_i\ne mx\)。
当 \(a_i>2mx\) 时,此时用不了“关键结论”,所以直接暴力枚举 \(1\) 至 \(i-1\) 更新答案。
否则,当 \(2a_i>mx\) 且 \(a_i\le 2mx\) 时,直接将 \(ans\) 修改为 \(\max(mx,a_i)\)。这是因为根据结论,加入 \(a_i\) 后 \(\max(mx,a_i)\) 已经是整个序列可能达到的最大值,而又由结论可得 \(f(mx,a_i)=\max(mx,a_i)\),不能再大了。
最后,如果 \(2a_i\le mx\),那么我们令 \(ans=\max(ans,f(a_i,mx))\)。证明也很简单,考虑分讨:
(1)如果 \(a_i\le mx'\),那么对于任意的 \(v\le mx'\),我们有 \(f(a_i,v)\le \max(a_i,v)\le mx' \le f(mx',mx)\)。也就是说和任何一个不大于次大值的数计算出的 \(f\) 值都不会超过原来的答案,那么只有 \(f(a_i,mx)\) 存在大于原 \(ans\) 的可能。
(2)如果 \(a_i> mx'\),我们有 \(f(a_i,v)\le a_i\le f(a_i,mx)\)。这里 \(f(a_i,mx)\) 直接地叉掉了所有的 \(f(a_i,v)\),那么只要以它更新 \(ans\) 即可。
综上,\(2a_i\le mx\) 时只需要 \(ans=\max(ans,f(a_i,mx))\)。
最后别忘了更新 \(mx=\max(mx,a_i)\)。从这一步可以看出 \(a_i>2mx\) 即暴力枚举更新最多只会存在 \(\log V\) 次,所以总复杂度 \(O(n \log V)\),可以接受。
code
#include <bits/stdc++.h>
//taskkill /f /im 未命名1.exe
#define ED cerr<<endl;
#define TS cerr<<"I AK IOI"<<endl;
#define cr(x) cerr<<x<<endl;
#define cr2(x,y) cerr<<x<<" "<<y<<endl;
#define cr3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define cr4(x,y,z,w) cerr<<x<<" "<<y<<" "<<z<<" "<<w<<endl;
#define popcnt __builtin_popcount
#define all(s) s.begin(),s.end()
#define bstring basic_string
//#define add(x,y) (x+=y)%=mod
#define pii pair<int,int>
#define epb emplace_back
#define pb push_back
#define mk make_pair
#define ins insert
#define fi first
#define se second
#define ll long long
//#define ull unsigned long long
using namespace std;
const int N=1e6+5,INF=2e9,mod=1e9+7;
int t,n,m;
int a[N];
#define f(x,y) (x%y+y%x)
void sol() {
scanf("%d",&n);int mx=0,mx2=0,ans=0;
for(int i=1;i<=n;++i) {
scanf("%d",&a[i]);
if(a[i]>=mx+mx) {
for(int j=1;j<i;++j) {
ans=max(ans,f(a[j],a[i]));
}
}
else if(a[i]+a[i]>mx&&a[i]!=mx) {
ans=max(mx,a[i]);
}
else ans=max(ans,f(a[i],mx));
mx=max(mx,a[i]);
printf("%d ",ans);
}
puts("");
}
int main()
{
scanf("%d",&t);
while(t--) {
sol();
}
return 0;
}

浙公网安备 33010602011771号