链接
A. Meaning Mean
题目:
思路:贪心,先升序排序,每次组合当前最小的两个数。答案就是最大的。(因为每次合并的损失最小)。
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int num[200005];
int t,n;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++) cin>>num[i];
sort(num+1,num+1+n);
int temp=0;
for(int i=2;i<=n;i++){
temp=(num[i-1]+num[i])/2;
num[i]=temp;
}
cout<<num[n]<<endl;
}
return 0;
}
B. Maximize Mex
题目与数据范围:
思路:
注意,每次只能选择给这个数加上x。所以考虑从0开始枚举这个数有没有出现过。
如果这个数出现过,并且还有多余的。就可以拿来填补下一个没有出现过的数字。那一个多余的数可以填补什么样的数字?这个数+任意倍x都可以填补。所以,只要这个数模x与要填补的数模x一样就可以互相填补。
因为只能加不能减,所以我们判断这个数用完没有,用完了再加入。而且数据范围在1e9,记得用map存。
复杂度为
代码:
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int num[200005];
int t,n,x;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n>>x;
map <int,int> cnt;
map <int,int> change;
for(int i=1;i<=n;i++) cin>>num[i],cnt[num[i]]++;
for(int i=0;i<=n;i++){
if(cnt[i]>1) change[i%x]+=cnt[i]-1;
else if(!cnt[i] && change[i%x]){
cnt[i]++;
change[i%x]--;
continue;
} else if(!cnt[i]){
cout<<i<<endl;
break;
}
}
}
return 0;
}
C1. Adjust The Presentation (Easy Version)
题目及数据范围:
思路:
一个人演示完了后,可以去任何一个位置。我们不需要考虑它究竟去了哪里,只要知道他去了最有利于满足题目要求的位置。这样就大大化简了题目。
如果有可能完成演示,则默认每个人都去了最优的点。如果这个人已经讲过了,则再次遇到直接跳过。重点关注一次也没讲过的人,他们的相对位置改变不了。
代码:
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
using namespace std;
int a[200005];
int b[200005];
bool vis[200005];
int t,n,m,q;
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>t;
while(t--){
cin>>n>>m>>q;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=m;i++) cin>>b[i];
int now=1;//当前讲到哪个人。
bool flag=true;
for(int i=1;i<=m;i++){
if(vis[b[i]]) continue;//这个人讲过了,随意出现都可以。
else if(b[i]==a[now]) vis[a[now]]=true,now++;//标记讲过了。
else {
cout<<"TIDAK"<<endl;
flag=false;
break;
}
}
if(flag) cout<<"YA"<<endl;
for(int i=1;i<=n;i++) vis[i]=false;
}
return 0;
}