[题解]BYOI Round 1 T1~T2

比赛页面

VP.

T1. P14524 意识解离

每出现一个 \(a[i-1]<a[i]\)(特别地,令 \(a[0]=-\infty\)),说明必须新增一个长度为 \(n-i+1\) 的序列。

因此,有解的充要条件是 \(\forall i\in[1,n],a[i]\ge \sum_{j=1}^i \big[a[j]>a[j-1]\big]\)

时间复杂度 \(O(n)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
int t,n,a[N];
inline bool solve(){
	for(int i=1,c=0;i<=n;i++){
		if(a[i]>a[i-1]) c++;
		if(a[i]<c) return 0;
	}
	return 1;
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>t;
	a[0]=-2e9;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;i++) cin>>a[i];
		cout<<(solve()?"Yes\n":"No\n");
	}
	return 0;
}

T2. P14525 幻想碎片

看到数据范围和时限(500ms),复杂度大概是 \(O(n^3)\) 的。

我们枚举左右边缘 \(l,r\),中间部分看做一个长度为 \(n\) 的序列。

对于行数 \(\ge\) 列数,只需求出该序列长度 \(\ge (r-l+1)\) 的最大子段和,再乘上列数 \((r-l+1)\) 即可计入贡献。

对于行数 \(\le\) 列数,我们发现不好统计。但是将矩阵转置一下,就转化为行数 \(\ge\) 列数了!

时间复杂度 \(O(n^3)\)

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=405,inf=1e15;
inline void chmx(int &x,int y){x=max(x,y);}
int n,m,a[N][N],s[N][N],t[N],ans=-inf;
inline void solve(){
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[i][j]=s[i][j-1]+a[i][j];
	for(int i=1;i<=m;i++){
		for(int j=i;j<=m;j++){
			if(j-i+1>n) continue;
			for(int k=1;k<=n;k++) t[k]=t[k-1]+s[k][j]-s[k][i-1];
			int l=j-i+1,s=t[l],mx=t[l];
			for(int k=l+1;k<=n;k++) s=max(t[k]-t[k-l],s+t[k]-t[k-1]),mx=max(mx,s);//len>=l的最大子段和
			ans=max(ans,mx*l);
		}
	}
}
inline void tran(){
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) s[j][i]=a[i][j];
	swap(n,m);
	for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=s[i][j]; 
}
signed main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	solve(),tran(),solve();
	cout<<ans<<"\n";
	return 0;
}
posted @ 2025-11-18 13:56  Sinktank  阅读(118)  评论(0)    收藏  举报
★CLICK FOR MORE INFO★ TOP-BOTTOM-THEME
Enable/Disable Transition
Copyright © 2023 ~ 2025 Sinktank - 1328312655@qq.com
Illustration from 稲葉曇『リレイアウター/Relayouter/中继输出者』,by ぬくぬくにぎりめし.