ABC351

A

link

算出两个队分别得了几分,让木青队的总得分比高桥队多\(1\)即可。

点击查看代码
#include<bits/stdc++.h>

using namespace std;

int gq,mq;

signed main(){
	
	int x;
	for(int i = 1;i <= 9;++ i){
		cin >> x;gq += x;
	}
	for(int i = 1;i <= 8;++ i){
		cin >> x;mq += x;
	}
	cout << gq-mq+1;
	
	return 0;
	
} 

B

link

暴力

点击查看代码
#include<bits/stdc++.h>

using namespace std;

int n;
char a[105][105];
int x,y;

signed main(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i){
		for(int j = 1;j <= n;++ j){
			cin >> a[i][j];
		}
	}
	
	for(int i = 1;i <= n;++ i){
		for(int j = 1;j <= n;++ j){
			char b;
			cin >> b;
			if(b != a[i][j]) x = i,y = j;
		}
	}
	
	cout << x << " " << y;
	
	return 0;
	 
}

C

link

依然暴力。
一个小问题:如果直接存\(2^{a_i}\)存不下,那么只存\(a_i\),两个合并即\(2^x+2^x\)\(2^{x+1}\),存\(x+1\)即可。

点击查看代码
#include<bits/stdc++.h>

using namespace std;

int n;
int a[200005];
int cn;

signed main(){
	
	cin >> n;
	while(n--){
		
		int x;
		cin >> x;
		
		a[++cn] = x;
		
		while(cn > 1){
			if(a[cn] == a[cn-1]){
				a[cn-1]++;
				cn--;
			}
			else break;
		}
		
	}
	
	cout << cn;
	
	return 0;
	
}

D

link

\(BFS\)加优化。
首先有一个“性质”。
如果把\(#\)周围的格子看做边界,那么可以将网格分为多个联通块,看哪个联通块中点加边界最多即可。
因为同一个联通块中所有点可以互相到达。
联通块用\(BFS\)搜,搜过的点赋为\(1\),可以不重复搜同一个联通块。
还有一个细节问题。
搜过的边界如果也赋为\(1\),那么下次就无法加上边界了,如果不赋,那么又会重复加。
那么每次的边界我们赋为当前横竖坐标组成一个唯一的数即可。

点击查看代码
#include<bits/stdc++.h>

#define int long long

using namespace std;

int n,m,cn,ans = 1;
char s[1005][1005];
int dx[] = {0,1,-1,0,0};
int dy[] = {0,0,0,1,-1};
int vs[1005][1005];

bool f(int x,int y){
	
	int xx = x,yy = y+1;
		
	if(xx > 0&&yy > 0&&xx <= n&&yy <= m)
		if(s[xx][yy] == '#')
			return false;
	
	yy -= 2;
		
	if(xx > 0&&yy > 0&&xx <= n&&yy <= m)
		if(s[xx][yy] == '#')
			return false;
	
	yy ++,xx++;
		
	if(xx > 0&&yy > 0&&xx <= n&&yy <= m)
		if(s[xx][yy] == '#')
			return false;
	
	xx -= 2;
		
	if(xx > 0&&yy > 0&&xx <= n&&yy <= m)
		if(s[xx][yy] == '#')
			return false;
	
	return true;
	
}

void bfs(int xq,int yq){
	
	queue<pair<int,int> > q;
	q.push({xq,yq});
	vs[xq][yq] = 1;
	cn = 1;
	
	while(!q.empty()){
		
		int x = q.front().first;
		int y = q.front().second;
		q.pop();
		
		for(int i = 1;i <= 4;++ i){
			
			int xx = x+dx[i];
			int yy = y+dy[i];
			
			if(xx <= 0||yy <= 0||xx > n||yy > m)
				continue;
			
			if(s[xx][yy] == '#') continue;
			
			if(vs[xx][yy] == 1||vs[xx][yy] == xq*10000+yq) continue;
			
			cn++;
			
			if(!f(xx,yy)){
				vs[xx][yy] = xq*10000+yq;
				continue;
			}
			
			vs[xx][yy] = 1;
			
			q.push({xx,yy});
			
		}
		
	}
	
}

void ch(int x,int y){
	
	cn = 0;
	
	bfs(x,y);
	
	ans = max(ans,cn);
	
}

signed main(){
	
	cin >> n >> m;
	for(int i = 1;i <= n;++ i)
		cin >> s[i]+1;
	
	for(int i = 1;i <= n;++ i){
		for(int j = 1;j <= m;++ j){
			if(vs[i][j] == 0&&s[i][j] != '#'&&f(i,j)) ch(i,j);
		}
	}
	
	cout << ans;
	
	return 0;
	
}

E

link

我们把表格旋转\(45\)度,再乘上根号\(2\),那么坐标就变成了\((x+y,x-y)\),四种变化就变成了\((x+2,y)\)\((x-2,y)\)\((x,y+2)\)\((x,y-2)\),即为曼哈顿距离\(/2\)
用前缀和算每个点到其他所有点的距离和即可,不要忘记除以\(2\)
前缀和的计算,每个点到前一个点的距离,加上前面的点数个这个点到前一个点的距离
还有一个小问题,由于每次改变的都是\(2\),所以要分为奇偶两组算。

点击查看代码
#include<bits/stdc++.h>

#define int long long

using namespace std;

int n;
int a[5][200005];
int cn[5];
int qzh[5][200005];
int ans;

signed main(){
	
	cin >> n;
	for(int i = 1;i <= n;++ i){
		int xq,yq;
		cin >> xq >> yq;
		int xx = xq+yq,yy = xq-yq;
		xq = xx,yq = yy;
		if(xq%2){
			a[1][++cn[1]] = xq;
			a[2][++cn[2]] = yq;
		}
		else{
			a[3][++cn[3]] = xq;
			a[4][++cn[4]] = yq;
		}
	}
	
	sort(a[1]+1,a[1]+1+cn[1]);
	sort(a[2]+1,a[2]+1+cn[2]);
	sort(a[3]+1,a[3]+1+cn[3]);
	sort(a[4]+1,a[4]+1+cn[4]);
	
	for(int i = 1;i <= 4;++ i){
		
		for(int j = 2;j <= cn[i];++ j){
			qzh[i][j] += qzh[i][j-1]+(j-1)*(a[i][j]-a[i][j-1]);
			ans += qzh[i][j];
		}
		
	}
	
	cout << ans/2;
	
	return 0;
	
} 
posted @ 2024-05-02 16:00  学贵坚持  阅读(51)  评论(0编辑  收藏  举报