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;
}