慕容琳的后花园
慕容琳的后花园
hgoi#20190506

T1-Fraction

给定n 求最大的分数a/b,使得a+b=n

解法

暴力枚举即可

ac代码

#include<bits/stdc++.h>
using namespace std;
int n;
int check(int a,int b)
{
    for(int i=2;i<=a;i++)
        if(a%i==0&&b%i==0)
            return 0;
    return 1;
}
int main()
{
    scanf("%d",&n);
    for(int i=(n-1)/2;i>=1;i--)
    {
        int j=n-i;
        if(check(i,j)){printf("%d %d\n",i,j);break;}
    }
    return 0;
}

T2-Maxim Buys an Apartment

Maxim想在大都会的莱恩大道上买一座新的公寓。这幢楼房共有 n 座公寓,从 1 到 n 编号排列在一个数列中。两座相邻公寓的编号相差为 1。有一些公寓已经被售出了,另外的一些是待售的。
Maxim时常拜访他的邻居,因此如果有一座待售公寓,其相邻公寓中至少有一座是已售出的,那么这座公寓很适合Maxim。Maxim已经知道了有 k 座公寓已被售出,但是他还不知道这些已售出公寓的编号是多少。
计算出适合Maxim的公寓数可能的最小值及最大值。

解法

第一小问,不是0就是1,判断一下就可以了
第二小问,如果3k>n,那就是n-k,不然就是2k

ac代码

#include<bits/stdc++.h>
using namespace std;
int n,m,k,ans1,ans2;
int main()
{
    scanf("%d%d",&n,&k);
    if(k&&k!=n)ans1=1;
    else ans1=0;
    m=n/3;
    if(m>=k)ans2=k*2;
    else ans2=n-k;
    printf("%d %d\n",ans1,ans2);
    return 0;
}

T3-Planning

Helen在大都会机场工作,她的任务是安排每天的航班起飞时刻。今天一共有n架飞机将要起飞,第i架飞机将在第i分钟起飞。
大都会机场是大都会最重要的交通枢纽,因此想要原封不动地按照起飞时刻表的时刻起飞是很困难的。今天的情况也是如此:由于技术原因,在今天一开始的k分钟内飞机不允许起飞,因此必须创建一个新的起飞时刻表。
所有的航班必须在第(k+1)分钟到第(k+n)分钟内(包括两端)起飞,而且每分钟仅能有一架飞机起飞。然而,航班起飞的先后顺序可以与最初的时刻表排好的顺序不同,重排的时刻表只有一个限制:飞机不能比它在初始时刻表中起飞的时刻还要早的时刻起飞(即:第i架飞机必须在第i分钟后或第i分钟时起飞)。
Helen知道第i架飞机起飞时刻每延误一分钟机场所需支付的额外花费ci是多少。帮助她找到额外花费最小的方案。

解法

显然的贪心,额外花费高的要安排在前面,所以弄一个堆,每次压进去一个再取出来一个,计算一下答案就行了

ac代码

#include<bits/stdc++.h>
using namespace std;
struct node{int v,num;bool operator<(const node&x)const{return v<x.v;}};
priority_queue<node>q;
int n,k,x,res[300010];
long long ans;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x),q.push({x,i});
        if(i>k)ans+=1ll*(i-q.top().num)*q.top().v,res[q.top().num]=i,q.pop();
    }
    for(int i=n+1;i<=n+k;i++)ans+=1ll*(i-q.top().num)*q.top().v,res[q.top().num]=i,q.pop();
    printf("%lld\n",ans);
    for(int i=1;i<=n;i++)printf("%d ",res[i]);
    return 0;
}

T4-Jury Meeting

现在有(n+1)个城市,其中第1~n个城市每个城市有一个人,第0个城市是人们需要聚集的地方。还有m条航班,每条航班从0到其他城市或从其他城市到0,当天即可抵达,现在需要选定一个时间段,长度为k天,使得这一个时间段里人们都在0城市工作(航班抵达和离开0城市的那一天不能进行工作),问把n个人送到0城市,工作完成后再送回去的最小花费。

解法

预处理出a数组和b数组,其中a[i]表示i时间所有人到0号城市的最小消费,b[i]表示i时间所有人都回到自己所在城市的最小消费,处理这两个数组需要遍历所有时间与所有的边,所以复杂度是O(t+m)的,非常优了

ac代码

#include<bits/stdc++.h>
using namespace std;
struct node{int to,next,w;}ea[100010],eb[100010];
int n,m,k,t,x,y,z,st,ed,cnta,cntb,heada[1000010],headb[1000010],disa[100010],disb[100010];
long long ans=-1,a[1000010],b[1000010];
void adda(){ea[++cnta]={x,heada[t],z},heada[t]=cnta;}
void addb(){eb[++cntb]={y,headb[t],z},headb[t]=cntb;}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&t,&x,&y,&z);
        if(!x)addb();else adda();
        //分为x去0的边和0去y的边,分开储存
    }
    cnta=cntb=0;
    for(int i=1;i<=1000000;i++)
    {
        a[i]=a[i-1];
        for(int j=heada[i];j;j=ea[j].next)
        {
            t=ea[j].to;
            if(!disa[t])cnta++,disa[t]=ea[j].w,a[i]+=disa[t];
            else if(disa[t]>ea[j].w)a[i]+=ea[j].w-disa[t],disa[t]=ea[j].w;
        }
        //计算当前a[i]
        if(!st&&cnta==n)st=i;
        //如果都能到达0号点,就从此刻开始
    }
    for(int i=1000000;i>=1;i--)
    {
        b[i]=b[i+1];
        for(int j=headb[i];j;j=eb[j].next)
        {
            t=eb[j].to;
            if(!disb[t])cntb++,disb[t]=eb[j].w,b[i]+=disb[t];
            else if(disb[t]>eb[j].w)b[i]+=eb[j].w-disb[t],disb[t]=eb[j].w;
        }
        //倒序计算当前b[i]
        if(!ed&&cntb==n)ed=i;
        //如果都能回到原来的城市,就最多遍历到此刻
    }
    if(st==0||ed==0){puts("-1");return 0;}
    //如果不能都到0号点或不能都回到原来的城市,无解
    for(int i=1;i<=1000000;i++)
    {
        if(i+k+1>ed)break;
        if(i<st)continue;
        if(ans==-1)ans=a[i]+b[i+k+1];
        else ans=min(ans,a[i]+b[i+k+1]);
    }
    //枚举计算答案
    printf("%lld\n",ans);
    return 0;
}
赞赏
https://secure.gravatar.com/avatar/8cbc0c58deea66b18e9a96cd4bdd6eea?s=256&d=monsterid&r=g

慕容琳

文章作者

发表评论

textsms
account_circle
email

慕容琳的后花园

hgoi#20190506
T1-Fraction 给定n 求最大的分数a/b,使得a+b=n 解法 暴力枚举即可 ac代码 #include<bits/stdc++.h> using namespace std; int n; int check(int a,int b) { for(int i=2;…
扫描二维码继续阅读
2019-05-06
功能