AtCoder Beginner Contest 302
A - Attack
Problem Statement
题意:敌人有\(A\)的耐力值,每次攻击敌人可以减少\(B\)的耐力值,问多少次敌人耐力值\(<=0\)?
Solution
题解:\(\dfrac{a}{b}\)上取整。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll a,b;
cin>>a>>b;
if(a%b==0)
cout<<a/b<<endl;
else cout<<a/b+1<<endl;
return 0;
}
B - Find snuke
Problem Statement
题意:给你一个\(n\)行\(m\)列矩阵,里面都是小写英文字母,输出在同一直线上出现的\(snuke\)。输出坐标。
Solution
题解:遍历一遍,找到\(s\)的位置进行\(check\)。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 110;
char a[N][N];
int n,m;
bool check(int i,int j)
{
bool ok = false;
if(i-4>=1)
if(a[i-1][j]=='n'&&a[i-2][j]=='u'&&a[i-3][j]=='k'&&a[i-4][j]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i-1<<" "<<j<<endl;
cout<<i-2<<" "<<j<<endl;
cout<<i-3<<" "<<j<<endl;
cout<<i-4<<" "<<j<<endl;
return ok;
}
if(i+4<=n)
if(a[i+1][j]=='n'&&a[i+2][j]=='u'&&a[i+3][j]=='k'&&a[i+4][j]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i+1<<" "<<j<<endl;
cout<<i+2<<" "<<j<<endl;
cout<<i+3<<" "<<j<<endl;
cout<<i+4<<" "<<j<<endl;
return ok;
}
if(j-4>=1)
if(a[i][j-1]=='n'&&a[i][j-2]=='u'&&a[i][j-3]=='k'&&a[i][j-4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i<<" "<<j-1<<endl;
cout<<i<<" "<<j-2<<endl;
cout<<i<<" "<<j-3<<endl;
cout<<i<<" "<<j-4<<endl;
return ok;
}
if(j+4<=m)
if(a[i][j+1]=='n'&&a[i][j+2]=='u'&&a[i][j+3]=='k'&&a[i][j+4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i<<" "<<j+1<<endl;
cout<<i<<" "<<j+2<<endl;
cout<<i<<" "<<j+3<<endl;
cout<<i<<" "<<j+4<<endl;
return ok;
}
if(i-4>=1&&j-4>=1)
if(a[i-1][j-1]=='n'&&a[i-2][j-2]=='u'&&a[i-3][j-3]=='k'&&a[i-4][j-4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i-1<<" "<<j-1<<endl;
cout<<i-2<<" "<<j-2<<endl;
cout<<i-3<<" "<<j-3<<endl;
cout<<i-4<<" "<<j-4<<endl;
return ok;
}
if(i+4<=n&&j+4<=m)
if(a[i+1][j+1]=='n'&&a[i+2][j+2]=='u'&&a[i+3][j+3]=='k'&&a[i+4][j+4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i+1<<" "<<j+1<<endl;
cout<<i+2<<" "<<j+2<<endl;
cout<<i+3<<" "<<j+3<<endl;
cout<<i+4<<" "<<j+4<<endl;
return ok;
}
if(i-4>=1&&j+4<=m)
if(a[i-1][j+1]=='n'&&a[i-2][j+2]=='u'&&a[i-3][j+3]=='k'&&a[i-4][j+4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i-1<<" "<<j+1<<endl;
cout<<i-2<<" "<<j+2<<endl;
cout<<i-3<<" "<<j+3<<endl;
cout<<i-4<<" "<<j+4<<endl;
return ok;
}
if(i+4<=n&&j-4>=1)
if(a[i+1][j-1]=='n'&&a[i+2][j-2]=='u'&&a[i+3][j-3]=='k'&&a[i+4][j-4]=='e')
{
ok = true;
cout<<i<<" "<<j<<endl;
cout<<i+1<<" "<<j-1<<endl;
cout<<i+2<<" "<<j-2<<endl;
cout<<i+3<<" "<<j-3<<endl;
cout<<i+4<<" "<<j-4<<endl;
return ok;
}
return ok;
}
int main()
{
cin>>n>>m;
for(int i = 1;i<=n;i++)
for(int j = 1;j<=m;j++)
cin>>a[i][j];
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++)
{
if(a[i][j]=='s')
{
if(check(i,j))return 0;
}
}
}
return 0;
}
C - Almost Equal
Problem Statement
题意:给你\(N\)个长度为\(M\)的字符串,问你能否对这些字符串重新排列,使得第\(i\)个和第\(i+1\)个字符串只有一个字母不一样,可以输出\(Yes\),否则\(No\).
Solution
题解:因为注意到\(N\)范围很小,可以直接暴力\(dfs\),先进性一个全排列,每次\(check\)是否满足。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,cnt;
const int N = 10;
string s[N];
int a[N];
bool vis[N];
map<int,string>mp;
bool yes;
void dfs(int step)
{
if(yes)return;
if(step>n)
{
bool ok = true;
for(int i = 1;i<n;i++)
{
int c = 0;
string t = mp[a[i]];
string t2 = mp[a[i+1]];
for(int j = 0;j<m;j++)
{
if(t[j]!=t2[j])c++;
}
if(c!=1)
{
ok = false;
break;
}
}
if(ok)yes = true;
return;
}
for(int i = 1;i<=n;i++)
{
if(!vis[i])
{
a[step] = i;
vis[i] = true;
dfs(step+1);
vis[i] = false;
a[step] = 0;
}
}
}
int main()
{
cin>>n>>m;
for(int i = 1;i<=n;i++)
cin>>s[i],mp[++cnt] = s[i];
dfs(1);
if(yes)cout<<"Yes\n";
else cout<<"No\n";
return 0;
}
D - Impartial Gift
Problem Statement
题意:要为两个人选礼物,从\(N\)个候选中选一个给\(A\),从\(M\)个候选中选一个给\(B\),问两个的价值相差不超过\(D\),问你两个礼物总和最大为多少?
Solution
题解:排序+双指针。因为我们优先选价值高的,如果不满足价值差小于\(D\)就移动价值大的那个指针,因为这个时候移动小的只会更厘普。
注意\(A,B\)的范围,小心爆\(long long\)
#include<bits/stdc++.h>
using namespace std;
__int128 read()
{
__int128 f = 1, w = 0;
char ch = getchar();
while (ch < '0' || ch>'9')
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch <= '9' && ch >= '0')
{
w = w * 10 + ch - '0';
ch = getchar();
}
return f * w;
}
void print(__int128 x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)print(x / 10);
putchar(x % 10 + '0');
}
typedef __int128 ll;
const int N = 2e5+10;
ll n,m,D;
ll a[N],b[N];
bool cmp(ll a,ll b)
{
return a>b;
}
int main()
{
n = read(),m = read(),D = read();
for(int i = 1;i<=n;i++)
a[i] = read();
for(int i = 1;i<=m;i++)
b[i] = read();
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+m,cmp);
ll c = 1,d = 1;
bool ok = false;
ll ans = 0;
while(c<=n&&d<=m)
{
if((a[c]-b[d]>=0&&a[c]-b[d]<=D)||(b[d]-a[c]>=0&&b[d]-a[c]<=D))
{
ok = true;
ans = a[c]+b[d];
break;
}
else
{
if(a[c]>b[d])c++;
else d++;
}
}
if(ok)
print(ans);
else cout<<-1<<endl;
return 0;
}
E - Isolation
Problem Statement
题意:给你一个无向图,\(N\)个点,编号\(1\)到\(N\),并且初始状态没有边。
给你\(Q\)个询问,每次询问输出当前孤立的点的数目。
\(1\) $ u$ $ v$ :连接\(uv\)
$2 $ $ v$ :删除和\(v\)相连的所有边
Solution
题解:用\(set\)存边,先说操作一:对于点x,y,连接他们两个,如果set[x].size()==0的话,那现在连上了,那答案-1,同样对于\(y\)也是。对于操作二:删边操作。我们遍历该点连的所有边,用lower_bound直接erase掉对应点和\(x\)的边,如果删完之后edge[y].size()变为0了,那答案+1,最后如果对于操作的点\(x\),如果edge[x].size是大于0的,那答案-1,edge[x].clear。解决。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+10;
int cnt;
map<pair<int,int>,int>mp;
set<int>edge[N];
int main()
{
int n,q;
cin>>n>>q;
cnt = n;
for(int i = 1;i<=q;i++)
{
int op;
cin>>op;
if(op==1)
{
int x,y;
cin>>x>>y;
cnt -= edge[x].empty(),cnt-=edge[y].empty();
edge[x].insert(y);
edge[y].insert(x);
cout<<cnt<<endl;
}
else
{
int x;
cin>>x;
for(auto y:edge[x])
{
edge[y].erase(edge[y].lower_bound(x));
cnt += edge[y].empty();
}
if(edge[x].size())
cnt++,edge[x].clear();
cout<<cnt<<endl;
}
}
return 0;
}
F - Merge Set
Problem Statement
题意:给你\(N\)个集合,我们每次选2个集合进行合并,这两个集合要至少有一个一样的元素才能合并,问至少合并多少次能使得集合中包含\(1\)到\(M\)所有元素。
Solution
思路:是01bfs。我们考虑把\(N\)个集合看成\(N\)个点,\(M\)个元素看成\(M\)个点,建图跑最短路。当前集合到集合内元素的距离设为0,集合元素到集合的距离设为1,跑bfs或者dijkstra都可以。因为是求合并次数,最后答案-1.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5+10;
struct Node
{
int y,v;
Node(int _y,int _v){y = _y;v = _v;};
};
set<pair<int,int>>q;
vector<Node>edge[N*2];
int n,m,k, dist[N*2];
inline void dijkstra(int s)
{
memset(dist,127,sizeof(dist));
dist[s] = 0;
q.clear();
for(int i = 1;i<=n+m;i++)
{
q.insert({dist[i],i});
}
while(!q.empty())
{
int x = q.begin()->second;//离起点最近的点的下标
q.erase(q.begin());
for(auto i:edge[x])
{
if(dist[x]+i.v<dist[i.y])
{
q.erase({dist[i.y],i.y});
dist[i.y]= dist[x]+i.v;
q.insert({dist[i.y],i.y});
}
}
}
}
int main()
{
cin>>n>>m;
for(int i = 1;i<=n;i++)
{
int sz;
cin>>sz;
for(int j = 1;j<=sz;j++)
{
int x;
cin>>x;
edge[i].push_back(Node(x+n,0));
edge[x+n].push_back(Node(i,1));
}
}
dijkstra(1+n);
ll ans = dist[m+n];
if(ans>(1<<30))ans= 0;
cout<<ans-1<<endl;
return 0;
}
标签:AtCoder,cout,int,302,long,edge,&&,ABCDEF,ll
From: https://www.cnblogs.com/nannandbk/p/17487010.html