The 2023 ICPC Asia Regionals Online Contest (I)部分题解

The 2023 ICPC Asia Regionals Online Contest (I)

L-KaChang!

题意:

给了n个程序的运行时间和标程的运行时间,问时限开到标程的多少倍,所有程序均可通过,并且至少开到二倍

思路:

对n个程序的运行时间取max,max/k向上取整,如果小于2,直接输出2

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,T;
    cin>>n>>T;
    int mx=0;
    while(n--){
        int t;
        cin>>t;
        mx=max(mx,t);
    }
    int k=ceil(mx*1.0/T);
    cout<<(k<2?2:k)<<endl;
}

A-Qualifiers Ranking Rules

题意:

对两场比赛的学校排名进行归并,每场比赛每个学校只记最高队伍排名,排名相同时第一场优先

思路:

先对两场的排名进行去重,然后依次从第一场和第二场各取出一所学校,如果未加入最终排名,则加入,否则跳过,有一场取完后就只从另一场取,直到取完所有学校

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,m;
    cin>>n>>m;
    vector<string>a,b;
    map<string,int>mp;
    string s;
    for(int i=0;i<n;i++){
        cin>>s;
        if(mp[s]==0){
            mp[s]=1;
            a.push_back(s);
        }
    }
    mp.clear();
    for(int i=0;i<m;i++){
        cin>>s;
        if(mp[s]==0){
            mp[s]=1;
            b.push_back(s);
        }
    }
    vector<string>ans;
	n=a.size(),m=b.size();
	mp.clear();
    int l=0,r=0;
    while(l<n||r<m){
        if(l<n&&mp[a[l]]==0){
            mp[a[l]]=1;
            ans.push_back(a[l]);
        }
        if(r<m&&mp[b[r]]==0){
            mp[b[r]]=1;
            ans.push_back(b[r]);
        }
        l++,r++;
    }
    for(auto s:ans){
        cout<<s<<endl;
    }
}

D-Transitivity

题意:

给定n个点,m条边的一个简单无向图。定义一个图是可传递的,如果两点之间有路径,则两点之间有条边,要求添加最少且至少一条边使图依然是可传递的

思路:

先判连通块,如果所有连通块都是可传递的,则连接最小的两个连通块,否则使每个连通块可传递

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
vector<int>a[1000010];
int flag[1000010];
pair<int,int> dfs(int r){
    pair<int,int>t(1,0);
    flag[r]=1;
    for(int i=0;i<a[r].size();i++){
        if(flag[a[r][i]]){
            t.second++;
        }else{
            pair<int,int>p=dfs(a[r][i]);
            t.first+=p.first;
            t.second+=p.second+1;
        }
    }
    return t;
}
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i=0;i<m;i++){
        int u,v;
        cin>>u>>v;
        a[u].push_back(v);
        a[v].push_back(u);
    }
    int ans=0;
    vector<int>b;
    for(int i=1;i<=n;i++){
        if(flag[i]==0){
            pair<int,int>t=dfs(i);
            ans+=(t.first*(t.first-1)/2-t.second/2);
            b.push_back(t.first);
        }
    }
    sort(b.begin(),b.end());
    if(ans==0){
        cout<<b[0]*b[1]<<endl;
    }else{
        cout<<ans<<endl;
    }
}

J-Minimum Manhattan Distance

题意:

给定两个圆C1,C2,这两个圆被用直径表示,求C2上或内的一个点到C1内点的最小曼哈顿距离的期望值

思路:

如果C1的圆心在C2的左边,肯定是C2左半部分某点到C1圆心的曼哈顿距离,否则则是C2右半部分到C1圆心的曼哈顿距离,通过圆心和半径表示出圆的方程,用方程把x坐标或y坐标表示出,带入曼哈顿距离公式,然后三分求解

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
void solve(){
    double x1,y1,x2,y2;
    cin>>x1>>y1>>x2>>y2;
    double r1=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))/2;
    double x3,y3,x4,y4;
    cin>>x3>>y3>>x4>>y4;
    double r2=sqrt((x3-x4)*(x3-x4)+(y3-y4)*(y3-y4))/2;
    pair<double,double> o1,o2;
    o1={(x1+x2)/2,(y1+y2)/2};
    o2={(x3+x4)/2,(y3+y4)/2};
    double l=o2.y-r2,r=o2.y+r2;
    double ans=1e8;
    double pos=1e-7;
    if(o1.x<o2.x){
            while(r-l>=1e-5){
            double mid1=(l+r)/2-pos;
            double mid2 = (l + r) / 2 + pos;
            double f1 = abs(0-sqrt(r2 * r2 - (mid1 - o2.y) * (mid1 - o2.y)) + o2.x - o1.x) + abs(mid1 - o1.y);
            double f2=abs(0-sqrt(r2*r2-(mid2-o2.y)*(mid2-o2.y))+o2.x-o1.x)+abs(mid2-o1.y);
            if(f1>=f2){
                l=mid1;
                ans=f1;
            }else{
                r=mid2;
                ans=f2;
            }
        }	
    }else{
        while(r-l>=1e-5){
            double mid1=(l+r)/2-pos;
            double mid2 = (l + r) / 2 + pos;
            double f1 = abs(sqrt(r2 * r2 - (mid1 - o2.y) * (mid1 - o2.y)) + o2.x - o1.x) + abs(mid1 - o1.y);
            double f2=abs(sqrt(r2*r2-(mid2-o2.y)*(mid2-o2.y))+o2.x-o1.x)+abs(mid2-o1.y);
            if(f1>=f2){
                l=mid1;
                ans=f1;
            }else{
                r=mid2;
                ans=f2;
            }
        }
    }
    printf("%.10f\n",ans);
}

int main(){
    int _=1;
    cin>>_;
    while(_--)
        solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值