代码部落 20250629 CSP-J复赛 模拟赛

网址:代码部落

密码:666888

一: 相濡以沫 β(代码请自写)

        签到题,如果a[i]<=a[i+1]  a[i]=a[i+1],反之,直接输出No

二   共同富裕(代码请自写)

       签到题,用sort+前缀和   如果最富有的个⼈的平均值都⼩于 x的话, ⼈数就不能满⾜,(把富有的⼈换成不富有的 ⼈,平均值只会缩⼩) 我们将数组从⼤到⼩排序,依次判断前 i富有的⼈的均值满不满⾜即可。

        注:开 long long !开 long long !开 long long !

三  序列消消乐

        思路:如果数据有解,2~n必定存在一个等号'=',删除它后,剩余的序列可以按照给定逻辑反复处理,将问题转化为线性转移。令dp[i]表示前i个数是否都能被删除。显然,只有当存在一个j使得f[j]=1且aj+1=ai时,我们才能选择两个数aj+1和ai来删除范围内的所有数,从而使得dp[i]=1。时间复杂度为O(n^2),可以获得60分。

        优化上述逻辑,能否根据aj+1=ai=x 这个数值直接判断前⾯ 1~j能否删除,从⽽减少内层for循环 考虑维护⼀个 vis数组, vis[x]=1表示数值 x前⾯的数都能被删除,当 a[i]=x如果vis[x]=1 ,即可得出f[i]=1 如果 f[i-1]=1,可得出vis[x]=1;

        代码

#include
#define int long long
using namespace std;
const int N=1e5+10;
int t,n,m,a[N];
int b[N],sum;
void check(){

	for(int i=1;i<=n;i++){
		if(b[i]>=1ll*m*(n-i+1)){
			cout<>t;
	while(t--){
		cin>>n>>m;
		memset(b,0,sizeof(b));
		for(int i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+1+n);
		for(int i=n;i>=1;i--) b[i]=b[i+1]+a[i];
		check();
		
	}
	return 0;
}

四 黑白翻转

        思路:⾸先翻转是以⾏为单位的,我们可以想到⼀⾏⼀⾏的线性转移 设状态 fi为前i的"独特性"总和的最⼤值 考虑 fi和fi-1 之间⽆法转移 因为我们不清楚地i⾏的状态,不清楚第i-1⾏的状态 同样要计算fi也需要知道i+1⾏的状态 所以我们丰富下状态fi,a,b,c 表示第i-1,i,i+1 这三⾏的翻转状态分别为a,b,c (0表示不翻转, 1表示翻转) 的情况下, 前i⾏的"独特性"总和的最⼤值 同时定义gi,a,b,c 表示第i-1,i,i+1 这三⾏的翻转状态分别为a,b,c的情况下, 第i ⾏每个⽹格数 的"独特性"总和. 这个可以直接在原图的基础上以 O(n)的时间复杂度直接计算出来. 最后可得状态转移⽅程为:

        fi,a,b,c = max (d=0,d=1) fi-1,d,a,b+gi,a,b,c

代码:

#include
using namespace std;
const int N=1e3+10;
int n,m,d[N][N],dp[N][3][3][3];
int check(int x,int y,int a,int b,int c){
	int t=0;
	if(y-1>=1){
		t+=(d[x][y]!=d[x][y-1]);
	}
	if(y+1<=m){
		t+=(d[x][y]!=d[x][y+1]);
	}
	if(x-1>=1){
		t+=((d[x][y]^b)!=(d[x-1][y]^a));
	}
	if(x+1<=n){
		t+=((d[x][y]^b)!=(d[x+1][y]^c));
	} 
	return t*t*t;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			scanf("%1d",&d[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		for(int a=0;a<=1;a++){
			for(int b=0;b<=1;b++){
				for(int c=0;c<=1;c++){
					for(int d=0;d<=1;d++){
						dp[i][a][b][c]=max(dp[i][a][b][c],dp[i-1][d][a][b]);
					}
					for(int j=1;j<=m;j++){
						dp[i][a][b][c]+=check(i,j,a,b,c); 
					}
				}
			}
		}	
	}
	int maxx=0;
	for(int a=0;a<=1;a++){
		for(int b=0;b<=1;b++){
			for(int c=0;c<=1;c++){
				maxx=max(maxx,dp[n][a][b][c]);
			}
		}
	}
	printf("%d",maxx);
	return 0;
}

你可能感兴趣的:(代码部落 20250629 CSP-J复赛 模拟赛)