AtCoder Beginner Contest 216 個人題解
比賽鏈接:AtCoder Beginner Contest 216
每篇一圖
A題 Signed Difficulty
題目大意:
給出一個小數,根據小數部分改寫 \(+,-\)
思路解析:
直接判斷即可
AC代碼:
#include<bits/stdc++.h>
using namespace std;
int main(){
int x,y;
scanf("%d.%d",&x,&y);
if(y<=2)cout<<x<<"-"<<endl;
else if(y<=6)cout<<x<<endl;
else cout<<x<<"+"<<endl;
}
B題 Same Name
題目大意:
給出 \(n\) 個人的名字,每個人的名字由兩部分組成,問是否有重名的人
思路解析:
- 暴力枚舉匹配
- STL-map判斷
AC代碼:
- 暴力做法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
struct node{
string x,y;
}s[maxn];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>s[i].x>>s[i].y;
int flg=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(s[i].x==s[j].x&&s[i].y==s[j].y)flg=1;
}
}
if(flg)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
- map做法
#include<bits/stdc++.h>
using namespace std;
map<string,map<string,int> >a;
string s,t;
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>s>>t;
if(a[s][t]){
cout<<"Yes"<<endl;
return 0;
}
a[s][t]=1;
}
cout<<"No"<<endl;
}
C題 Many Balls
題目大意:
有一個盒子,你可以進行兩種操作:1.往盒子里放一個球 2.使盒子里的球翻倍
問一個可行的操作方案使盒子里的球從 \(0\) 到 \(n\) ,操作最多 \(120\) 次
思路解析:
我們很容易想到可以從 \(n\) 往回推,這樣操作 \(1\) 就變成了 \(/2\) ,操作 \(2\) 就變成了 \(-1\) ,當\(n\) 為偶數,就可以 \(/2\) 當 ,\(n\) 為奇數就可以 \(-1\) ,直到盒子里的球為 \(0\)
AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ll n;
cin>>n;
string ans;
while(n){
if(n%2==0){
ans+='B';
n/=2;
}
else{
ans+='A';
n--;
}
}
for(int i=ans.size()-1;i>=0;i--)cout<<ans[i];
}
D題 Pair of Balls
題目大意:
我們有 \(n\) 種顏色的球,每種顏色有兩個球,總共有 \(2n\) 個球,這些球被放在 \(m\) 個棧中,每次只能從兩個不同棧頂取出相同顏色的球,問是否可以把球全部取出(好像消消樂)
思路一解析:
首先我們思考,很直觀的考慮,什么時候會不能達成目的:
靈魂畫手上線:
由題意我們很容易看出,如果要想清空一個棧的話每個棧頂的數字一定需要先於他下面的數刪除,所以這就形成了拓撲關系。
在觀察數據,我們又可以發現由於每個數字存在兩個,所以以每個數字為節點,至多向外連兩條有向邊,我們就可以把問題轉化為了有向圖的拓撲排序來處理。
思路二解析:
開棧模擬
思路一代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=4e5+5;
int e[maxn],h[maxn],nex[maxn],id;
int ans,in[maxn];
queue<int>q;
void add(int x,int y){
e[++id]=y;
nex[id]=h[x];
h[x]=id;
}
int main(){
int n,m;
cin>>n>>m;
for(int j=1;j<=m;j++){
int k,pre,x;
cin>>k>>pre;
for(int i=2;i<=k;i++){
cin>>x;
add(x,pre);
in[pre]++;
pre=x;
}
}
for(int i=1;i<=n;i++){
if(in[i]==0)q.push(i);
}
while(q.size()){
int top=q.front();
q.pop();
ans++;
for(int i=h[top];i;i=nex[i]){
int j=e[i];
in[j]--;
if(in[j]==0)q.push(j);
}
}
if(ans==n)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
思路二代碼
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int maxn=8e5+5;
int pos[maxn][3];
stack<int>s[maxn];
queue<pii>q;
int sum[maxn];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int k,op;
cin>>k;
for(int j=1;j<=k;j++){
cin>>op;
s[i].push(op);
if(pos[op][0]==0)pos[op][0]=i;
else pos[op][1]=i;
}
sum[s[i].top()]++;
if(sum[s[i].top()]==2)q.push(make_pair(pos[s[i].top()][0],pos[s[i].top()][1]));
}
while(!q.empty()){
pii top=q.front();
q.pop();
s[top.first].pop();
if(s[top.first].size())
{
sum[s[top.first].top()]++;
if(sum[s[top.first].top()]==2)
q.push(make_pair(pos[s[top.first].top()][0],pos[s[top.first].top()][1]));
}
s[top.second].pop();
if(s[top.second].size())
{
sum[s[top.second].top()]++;
if(sum[s[top.second].top()]==2)
q.push(make_pair(pos[s[top.second].top()][0],pos[s[top.second].top()][1]));
}
}
for(int i=1;i<=m;i++){
if(s[i].size()){
cout<<"No"<<endl;
return 0;
}
}
cout<<"Yes"<<endl;
}
E題 Amusement Park
題目大意:
給你 \(n\) 個數,你可以選擇 \(k\) 次,每次選擇一個數后這個數就會 \(-1\) ,問你能得到選擇數的和的最大值
思路解析:
首先我們考慮暴力的做法:直接把數都扔到 set
里,每次取最大然后讓他 \(-1\) 再把它扔回去就行了,但是這么做穩 \(TLE\)
如何優化:推一推,手搓一下就完了
AC代碼:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
ll n,k,a[maxn],cnt,ans;
bool cmp(ll x,ll y){
return x>y;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++){
ll x=a[i]-a[i+1];
if(cnt+i*x<=k){
ans+=(a[i]+a[i+1]+1)*x/2*i;
cnt+=i*x;
}
else{
k-=cnt;
ans+=(a[i]+a[i]-(k/i)+1)*(k/i)/2*i;
ans+=(k%i)*(a[i]-(k/i));
break;
}
}
cout<<ans<<endl;
}
F題 Amusement Park
題目大意:
給你兩個長度為 \(n\) 數組 \(A\) ,\(B\) ,分別對應位置 \(1-n\) ,問有多少個S of {1,2,...,n}的子集滿足 \(max_{i\in S}A_i \geq \sum_{i\in S}B_i\)
思路解析:
首先將 \(A\) 從小到大排序,這樣我們遍歷 \(i\) ,當前的 \(A[i]\) 就是最大的,我們就把式子中的第一個 \(max\) 去掉了。
剩下的部分我們可以用 \(DP\) 背包來做,具體怎么做,不會
AC代碼:
G題 01Sequence
題目大意:
你需要構造一個 \(01\) 串,滿足給出的每個 \(L_i,R_i,X_i,\) 在 \([L,R]\) 中至少有 \(X\) 個 \(1\)
輸出滿足條件的 \(01\) 串且 \(01\) 串中 \(1\) 最少
思路解析:
貪心,數據結構維護一下就行,具體怎么寫,不會
AC代碼: