FYN OI奋斗之路4~

XJOI 奋斗群群赛6

A - Fraction

题意

输入一个数n,输出一对和为n且互质的数。

题解

调用了STL库中的__gcd函数,最大公约数为1即为两数互质。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n;
    cin>>n;
    for(int i=n/2;i>=1;i--){
        if(__gcd(i,n-i)==1){
            cout<<i<<" "<<n-i;
            return 0;
        }
    }
}

B - Maxim Buys an Apartment

题意

输入一个数n代表房子总数,再输入一个数k代表有人住的房子数量。n个房子排成直线,如果一个空房子的左侧或右侧有人住,则该房子为好,要求求出最小和最大的好的房子的数量。

题解

水题,分类讨论即可。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int n,k;
    cin>>n>>k;
    if(n==k||k==0){
        cout<<"0"<<" "<<"0";
    }
    else if(k<=n/3){
        cout<<"1"<<" "<<2*k;
    }
    else cout<<"1"<<" "<<n-k;
}

C - Planning

题意

给出n个航班和其延误代价,每个航班应在第i分钟出发,否则每延误一分钟付出相应代价,因某种原因,这些航班在开始的k分钟不能起飞,要求从k+1分钟起排出一张时间表,使得代价最小。

题解

基本算法贪心,在这里想到通过维护优先队列使时间复杂度降至O(logN),WA的两次是因为爆int了。

#include<bits/stdc++.h>
using namespace std;
struct planning_s {
    int x;
    int num;
    friend bool operator < (planning_s u,planning_s v) {
        return u.x<v.x;
    }
}a[300001];
int main() {
    int n,k;
    int ans[300001];
    long long int res=0;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i].x);
        a[i].num=i;
    }
    priority_queue <planning_s> q;
    for(int i=1;i<=k;i++) {
        q.push(a[i]);
    }
    for(int i=k+1; i<=k+n; i++) {
        if(i<=n) {
            q.push(a[i]);
        }
        planning_s  temp=q.top();
        q.pop();
        res=res+(long long int)(i-temp.num)*(long long int)(temp.x);
        ans[temp.num]=i;
    }
    cout<<res<<endl;
    for(int i=1; i<=n; i++) {
        printf("%d ",ans[i]);
    }
    return 0;
}

D - Jury Meeting

题意

输入n,有n+1个城市从0标号至n,其中0表示大都会,其余的城市每个城市都住有一个人,输入m,代表有m个航班,每个航班有四个数据:日期,出发城市,到达城市,价格,再输入k,要求求出使这n个人通过航班到达城市0,并停留k天后,再乘航班返回原城市的最小代价。

题解

预处理时对于每一架航班,使用结构体存储它的四个数据,之后按出发日期进行排序,之后正着扫一遍出发的最小价格,反向扫一遍返航的最小价格即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
const ll inf=1e17;
const int MAXN=2000100;
struct node{
    ll d;
    ll f;
    ll t;
    ll c;
}a[MAXN];
bool cmp(node a,node b){
    return a.d<b.d;
}
ll b[MAXN],ans[MAXN],ans1[MAXN];
int main(){
    ll i,j;
    ll n,m,k;
    cin>>n>>m>>k;
    for(i=1;i<=MAXN;i++){
        b[i]=-1;
        ans[i]=inf;
    }
    for(i=1;i<=m;i++){
        cin>>a[i].d>>a[i].f>>a[i].t>>a[i].c;
    }
    sort(a+1,a+m+1,cmp);
    ll num=0,s=0;
    for(i=1;i<=m;i++){
        if(a[i].f==0){
            continue;
        }
        if(b[a[i].f]==-1){
            num++;
            b[a[i].f]=a[i].c;
            s=s+a[i].c;
        }
        else{
            if(b[a[i].f]>a[i].c){
                s=s-b[a[i].f];
                b[a[i].f]=a[i].c;
                s=s+a[i].c; 
            }
        }
        if(num==n){
            ans[a[i].d]=s;
        }
    }
    num=0;s=0;
    for(i=1;i<=MAXN;i++){
        b[i]=-1;
        ans1[i]=inf;
    }
    for(i=m;i>=1;i--){
        if(a[i].t==0){
            continue;
        }
        if(b[a[i].t]==-1){
            num++;
            b[a[i].t]=a[i].c;
            s=s+a[i].c;
        }
        else{
            if(b[a[i].t]>a[i].c){
                s=s-b[a[i].t];
                b[a[i].t]=a[i].c;
                s=s+a[i].c;
            }
            if(num==n){
                ans1[a[i].d]=s;
            }
        }
        if(num==n){
            ans1[a[i].d]=s;
        }
    }
    for(i=1;i<=1000001;i++){
        if(ans[i]!=inf) break;
    }
    j=i;
    for(i=j+1;i<=1000001;i++){
        ans[i]=min(ans[i-1],ans[i]);
    }
    for(i=1000001;i>=1;i--){
        if(ans1[i]!=inf) break;
    }
    j=i;
    for(i=j-1;i>=1;i--){
        ans1[i]=min(ans1[i],ans1[i+1]);
    }
    ll res=inf;
    for(i=1;i<=1000001;i++){
        if(ans[i]==inf||ans1[i+k+1]==inf) continue;
        res=min(ans[i]+ans1[i+k+1],res);
    }
    if(res==inf){
        cout<<-1<<endl;
    }
    else{
        cout<<res<<endl;
    }
    return 0;
}

总结

最终RANK:2

待提升

D题比赛时我并没有ac,补题时也在cf上wa了n遍,D题暴露出来最主要的问题就是对于多个数据的处理方面,后面是听从大佬意见使用结构体存储航班的四个数据,这个小技巧以后也可以使用.

FIGHTING!

                                                            2017年9月7日
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值