2020牛客暑假多校集训第八场(补题)
I – Interesting Computer Game
题目大意:
• 给了两个数组a与b。
• 第i步可以从a和b中选择一个数。
• 求最后选出的数中,不同的数要最多。
思路:我开始用map来模拟a与b数字的选择,但答案总是错误,实际上应该把不同的数当成图中的点。二元数组a,b当成是一条边,最后构成图,如果转化成图之后有的地方形成了环的话,说明其中的点多次出现,每个都可以取到,对于没有构成环的部分,可能有个点只出现过一次。(利用并查集来解)
#include<iostream>
#include<map>
using namespace std;
const int maxn=1e5+10,maxe=2e5+10;
map<int,int> mp;
int a[maxn],b[maxn];
bool vis[maxe];
int f[maxe],n;
int findfather(int x){
if(x!=f[x]) f[x]=findfather(f[x]);
return f[x];
}
void bin()
{
int x,y;
for(int i=1;i<=n;i++){
x=findfather(mp[a[i]]),y=findfather(mp[b[i]]);
if(x!=y){
f[x]=y;
if(vis[x]||vis[y]) vis[y]=1,vis[x]=1;
}
else vis[y]=1;
}
}
int main(){
int T;
cin>>T;
for(int k=1;k<=T;k++){
int num=1;
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
if(!mp[a[i]]) mp[a[i]]=num++;
if(!mp[b[i]]) mp[b[i]]=num++;
}
for(int i=1;i<=num;i++) f[i]=i,vis[i]=0;
bin();
int ans=num-1;
for(int i=1;i<num;i++){
if(f[i]==i&&vis[i]==0) ans--;
}
cout<<"Case #"<<k<<": "<<ans<<endl;
mp.clear();
}
}I – Interesting Computer Game
题意:
• 有n种菜,每种菜的数量为bi, 每个菜的盈利为 ai。
• 每个顾客必须从第1种菜开始,连续地吃,每种吃一个。
• 保证顾客最多的情况下,盈利最大。
思路:
由题意可以,顾客最多的数量就是b1,而且将b数组处理,后面每一位都比前面的数小,之后就可以比较数组a的前缀和,取出最大的数,因为b数组处理后每一位都比前面的数小,我们从后往前枚举前缀和。因为long long会超出,使用long double。
#include<iostream>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
int t,n,a[maxn],b[maxn];
long double c[maxn];
int main(){
cin>>t;
for(int k=1;k<=t;k++){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
c[i]=c[i-1]+a[i];
}
ll u=c[1];
a[1]=1;
for(int i=2;i<=n;i++){
if(c[i]<=u) a[i]=0;
else{
a[i]=1;
u=c[i];
}
}
b[0]=1e5+10;
for(int i=1;i<=n;i++){
cin>>b[i];
b[i]=min(b[i-1],b[i]);
}
int l=0;
long double ans=0;
for(int i=n;i>=1;i--)
if(a[i]!=0){
ans+=c[i]*(b[i]-l);
l=b[i];
}
printf("Case #%d: %d %.0Lf\n",k,b[1],ans);
}
}
360集团公司福利 405人发布