前言
这是我第
4
4
4 次做出
F
F
F 题,庆祝上蓝!
正题
本题解提供 A − F A-F A−F 题题解,欢迎诸位大佬参考。
第 1 题 Penalty Kick
照例很水,模拟即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int n; cin>>n;
for (int i=1; i<=n; i++){
if (i%3==0) cout<<"x";
else cout<<"o";
}
return 0;
}
第 2 题 Farthest Point
也是很简单,枚举即可。注意为了 不丢失精度,我们用到了显而易见的定理:
如果:
x
2
>
y
2
x^2>y^2
x2>y2
那么:
x
>
y
x>y
x>y
#include <bits/stdc++.h>
using namespace std;
#define int long long
int x[110],y[110];
signed main(){
int n; cin>>n;
for (int i=1; i<=n; i++){
cin>>x[i]>>y[i];
}for (int i=1; i<=n; i++){
int mx=0; int id;
for (int j=1; j<=n; j++){
int dis=(x[j]-x[i])*(x[j]-x[i])+(y[j]-y[i])*(y[j]-y[i]);
if (dis>mx) mx=dis,id=j;
}cout<<id<<"\n";
}
return 0;
}
第 3 题 Colorful Beans
需要使用到
m
a
p
map
map 容器,不知诸位大佬是否知道。
这里不太方便讲述,就找了一篇:map 使用方法-优快云
#include <bits/stdc++.h>
using namespace std;
#define int long long
map <int,int> mp;
signed main(){
int n; cin>>n;
for (int i=1; i<=n; i++){
int u,v; cin>>v>>u;
if (!mp[u]) mp[u]=v;
else mp[u]=min(mp[u],v);
}int mx=0;
for (auto x:mp) mx=max(mx,x.second);
cout<<mx;
return 0;
}
第 4 题 Medicines on Grid
注意,题中的药物只会让你的能量值 变为 某个值,而 不是增加 !
那么我们可以注意到,我们把药物也变成图,两个药物 a , b a,b a,b 有边,仅当 a a a 处吃药后可以不使用任何药物走到 b b b。我们可以在 a a a 处 b f s bfs bfs,查看是否可以在药物作用内走到 b b b。
有了这个定义,我们可以求解问题了!假设我们的起点处的药物叫 S S S,作用范围 0 0 0,终点处是 T T T,作用范围是 0 0 0,那么我们可以在图上再跑 b f s bfs bfs,查看 S S S 是否可以走到 T T T。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int mx[4]={0,0,-1,1};
int my[4]={-1,1,0,0};
bool vis[310][310];
string mp[310];
int id[310][310],n,m,k;
vector <int> vc[310];
int x[310],y[310],e[310],ans[310];
void dfs(int x,int y,int ma){
queue <int> qx,qy,qz;
qx.push(x); qy.push(y); qz.push(0);
while (qx.size()){
int x=qx.front(); qx.pop();
int y=qy.front(); qy.pop();
int z=qz.front(); qz.pop();
if (z==ma) continue;
for (int i=0; i<4; i++){
int nx=x+mx[i];
int ny=y+my[i];
if (nx<1||ny<1||nx>n||ny>m) continue;
if (vis[nx][ny]||mp[nx][ny]=='#') continue;
qx.push(nx); qy.push(ny); qz.push(z+1);
vis[nx][ny]=1;
}
}
}void solve(int x){
for (auto u:vc[x]){
if (!ans[u]){
ans[u]=1; solve(u);
}
}
}signed main(){
cin>>n>>m;
for (int i=1; i<=n; i++){
cin>>mp[i]; mp[i]=" "+mp[i];
}cin>>k; int s,t;
for (int i=1; i<=k; i++){
cin>>x[i]>>y[i]>>e[i];
id[x[i]][y[i]]=i;
}for (int i=1; i<=n; i++){
for (int j=1; j<=m; j++){
if (mp[i][j]=='S') s=id[i][j];
if (mp[i][j]=='T'){
if (id[i][j]) t=id[i][j];
else k++,t=k,id[i][j]=k,x[k]=i,y[k]=j,e[k]=0;
}
}
}for (int i=1; i<=k; i++){
memset(vis,0,sizeof(vis));
vis[x[i]][y[i]]=1;
dfs(x[i],y[i],e[i]);
for (int j=1; j<=n; j++){
for (int k=1; k<=m; k++){
if (vis[j][k]&&id[j][k]){
vc[i].push_back(id[j][k]);
}
}
}
}ans[s]=1; solve(s);
cout<<(ans[t]?"Yes":"No");
return 0;
}
第 5 题 Minimize Sum of Distances
这道题看似很难,但这里介绍一种方法:换根 D P DP DP。
假设现在有一棵树(如下图),它的根是 u u u,我们要把根换到 v v v,求权值(每个点的深度乘点权和)变化。
那么可以发现,它增长了黑色权值和减红色权值和。黑色好算,是 v v v 的子树,红色可以用总权值减黑色计算。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[2010][2010];
bitset <2010> s[1010],ans[2010];
vector <int> vc[1010];
signed main(){
cin>>n>>m;
for (int i=1; i<=n; i++){
for (int j=1; j<=m; j++){
cin>>a[i][j];
}
}for (int j=1; j<=m; j++){
memset(s,0,sizeof(s));
for (int i=1; i<1000; i++) vc[i].clear();
for (int i=1; i<=n; i++){
s[a[i][j]][i]=1; vc[a[i][j]].push_back(i);
}for (int i=1; i<1000; i++){
for (auto x:vc[i]){
ans[x]^=s[i];
}
}
}int cnt=0;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
if (ans[i][j]) cnt++;
}
}cout<<cnt;
return 0;
}
第 6 题 Oddly Similar
看似不好做的一道难题,正所谓:
智商不够,数据结构来凑。
这道题用到的是 b o o l bool bool 类型数据结构,那非 b i t s e t bitset bitset 莫属啦!
B
i
t
s
e
t
Bitset
Bitset 是一种自带容器,它可以存储一个
01
01
01 数组,可以支持位运算,速度加快
64
64
64 倍!
这里介绍一下用法。
&
与运算,通常用于所有条件都成立才可以的决策。|
或运算,通常用于满足一个条件即可的决策,如背包问题。^
异或运算,通常运用在 奇偶问题 中。<<
>>
移位运算,通常配合使用前面的所有运算。
本题只会用到 ^
,其它的自行了解。本题的解法可以使用
n
n
n 个
n
n
n 位的
b
i
t
s
e
t
bitset
bitset,表示它们每行的关系。
如果我们枚举每一列,然后把所有一样的数归在一起,那么就可以把桶数字任意一个数异或上这个序列对应的 b i t s e t bitset bitset( 1 1 1 有 0 0 0 无)。
那么这时 ( i , j ) (i,j) (i,j) 的值为 1 1 1,证明它们之间有奇数个不同的数位。复杂度 O ( n 2 m 64 ) O(\frac{n^2m}{64}) O(64n2m),可以通过。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,a[2010][2010];
bitset <2010> s[1010],ans[2010];
vector <int> vc[1010];
signed main(){
cin>>n>>m;
for (int i=1; i<=n; i++){
for (int j=1; j<=m; j++){
cin>>a[i][j];
}
}for (int j=1; j<=m; j++){
memset(s,0,sizeof(s));
for (int i=1; i<1000; i++) vc[i].clear();
for (int i=1; i<=n; i++){
s[a[i][j]][i]=1; vc[a[i][j]].push_back(i);
}for (int i=1; i<1000; i++){
for (auto x:vc[i]){
ans[x]^=s[i];
}
}
}int cnt=0;
for (int i=1; i<=n; i++){
for (int j=i+1; j<=n; j++){
if (ans[i][j]) cnt++;
}
}cout<<cnt;
return 0;
}