为啥我不在的场都是上分场。(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;
}
posted @ 2025-07-21 20:27  Oier_szc  阅读(15)  评论(0)    收藏  举报