Codeforces Round #611 (Div. 3)

58 篇文章 0 订阅
13 篇文章 1 订阅

A. Minutes Before the New Year

题意:给一个时间,求到24:00 还有多少分钟。

思路:乱写。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int sel = 0;
int pre[N];
int suf[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        cout<<24*60-n*60-m<<endl;
    }
 
}

B. Candies Division

题意:n个糖果分给k个人。希望能分出最多的糖。且最大值和最小值差值不超过1。最大值个数不超过 k/2。

思路:贪心。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int sel = 0;
int pre[N];
int suf[N];
 
signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        int ave = n/m*m;
        int rem = min((n-n/m*m),m/2);
        cout<<ave+rem<<endl;
    }
 
}

C. Friends and Gifts

题意:n个人,互送礼物,有的人以及有送的对象了。有的人还没想好,帮他决定一下。要求是不能送给自己,每个人都收到一个礼物。

思路:先把即没人送也没想好送谁的分配好。防止自己送给自己。剩下的随便分给没有礼物的就行。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int sel = 0;
int pre[N];
int suf[N];
int mark[N] = {0};
int mark2[N] = {0};
 
signed main(){
    //cin>>t;
    while(t--){
        vector<int> f0;
        cin>>n;
        for(int i = 1 ; i <= n ; i ++){
            mark[i] = 0;
            mark2[i] = 0;
        }
        for(int i = 1 ; i <= n ; i ++){
            cin>>a[i];
            mark[a[i]] = 1;
            if(a[i] == 0){
                mark2[i] = 1;
                f0.push_back(i);
            }
        }
        for(int i = 1 ; i <= n; i  ++){
            if(!mark[i] && mark2[i]){
                int x = f0[f0.size()-1]; f0.pop_back();
                if(x == i){
                    int tmp = x;
                    x = f0[f0.size()-1];
                    f0.pop_back();
                    f0.push_back(tmp);
                }
                a[x] = i;
                mark[i] = 1;
            }
        }
        for(int i = 1 ; i <= n; i  ++){
            if(!mark[i]){
                a[f0[f0.size()-1]] = i;
                f0.pop_back();
            }
        }
        for(int i = 1 ; i <= n ; i ++){
            cout<<a[i]<<" ";
        }
        cout<<endl;
    }
}

D. Christmas Trees

题意:n棵圣诞树。要安排m个人的位置。使得每个人到最近的圣诞树的距离总和最小。

思路:比赛时想的是二分。贪心的去想。如果最远的那个人距离为x。那么每颗树的1 ~ x-1的范围内,一定是全塞满了人的,才会放到x的地方去。所以可以二分枚举这个最远距离。然后就把 每棵树 1 ~ x-1 的位置全填满。还剩下几个放到距离为x 的地方去就行了。但是后面填的细节有点麻烦。调了巨久。赛后bfs 3分钟 ac。bfs就是以没课树为起点,依次往外拓展一个距离。开map标记访问过的位置。太好写了!

AC代码1(二分):

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
int sel = 0;
map<int,int> mp;
 
bool check(int mid){
    int tmp = 2*mid;
    for(int i = 1 ; i <= n-1 ; i ++){
        int dis = a[i+1]-a[i]-1;
        tmp += min(2*mid,dis);
        if(tmp >= m) return true;
    }
    if(tmp >= m) return true;
    return false;
}
 
signed main(){
    //cin>>t;
    while(t--){
        cin>>n>>m;
        a[0] = -2e9;
        for(int i = 1 ; i <= n; i ++){
            cin>>a[i];
            mp[a[i]] = 1;
        }
        a[n+1] = 2e9;
        sort(a+1,a+1+n);
        int minn = 1e18;
        int l = 1, r = m;
        while(l <= r){
            int mid = (l+r)>>1;
            if(check(mid)){
                minn = min(minn,mid);
                r = mid-1;
            }else l = mid+1;
        }
        int res = 0;
        int cnt = 0;
        for(int i = 1 ; i <= n ; i ++){
            for(int j = 1 ; j < minn ; j ++){ // right
                if(!mp[a[i]+j]){
                    mp[a[i]+j] = 1;
                    ans[cnt ++] = a[i]+j;
                    res += min(j,abs(a[i+1]-(a[i]+j)));
                }else break;
            }
            for(int j = 1 ; j < minn ; j ++){ // left
                if(!mp[a[i]-j]){
                    mp[a[i]-j] = 1;
                    ans[cnt ++] = a[i]-j;
                    res += min(j,abs((a[i]-j)-a[i-1]));
                }else break;
            }
        }
        //cout<<cnt<<endl;
        for(int i = 1 ; i <= n ; i ++){
            if(cnt == m) break;
            if(!mp[a[i]+minn]){
                mp[a[i]+minn] = 1;
                ans[cnt ++] = a[i]+minn;
                res += minn;
            }
            if(cnt == m) break;
            if(!mp[a[i]-minn]){
                mp[a[i]-minn] = 1;
                ans[cnt ++] = a[i]-minn;
                res += minn;
            }
            if(cnt == m) break;
        }
        cout<<res<<endl;
        sort(ans,ans+m);
        for(int i = 0 ; i < m ; i ++)
            cout<<ans[i]<<" ";
        cout<<endl;
    }
}

AC代码2(bfs):

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
int sel = 0;
map<int,int> mp;
struct node{
    int x,w;
    node(int a,int b):x(a),w(b){}
};
queue<node> que;
 
signed main(){
    //cin>>t;
    while(t--){
        cin>>n>>m;
        a[0] = -2e9;
        for(int i = 1 ; i <= n; i ++){
            cin>>a[i];
            mp[a[i]] = 1;
            que.push(node(a[i],0));
        }
        int cnt = 0;
        int res = 0;
        while(1){
            node now = que.front();que.pop();
            res += now.w;
            if(now.w != 0) ans[cnt++] = now.x;
            if(cnt == m) break;
            if(!mp[now.x+1]) mp[now.x+1] = 1,que.push(node(now.x+1,now.w+1));
            if(!mp[now.x-1]) mp[now.x-1] = 1,que.push(node(now.x-1,now.w+1));
        }
        cout<<res<<endl;
        for(int i = 0 ; i < m ; i ++) cout<<ans[i]<<" ";
        cout<<endl;
    }
}

E. New Year Parties

题意:n个点。每个可以往左一格或者不动或者往右一个。问最后可以覆盖点的个数的最大和最小数量。

思路:贪心。先考虑最大。最左边的点肯定往左移动一格先。然后剩下的,看一下左中右那个点没覆盖,就去那个点,优先是先左再中再右。这样可以给右边的点足够的空间。 然后考虑最小值。先把重点去掉,看成一个点。因为他们全在一起就只算一个点,肯定一起移动。 最大值是要尽量往两边散开。最小值则是要尽量往中间靠拢。如果左边有点,那就和他站一起。 如果中间有点,那就不动。否则能往右就往右,这样右边的点就有可能与之合并。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e5+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];
int ans[N];
int sel = 0;
map<int,int> mp;
struct node{
    int x,w;
    node(int a,int b):x(a),w(b){}
};
queue<node> que;
 
signed main(){
    //cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n; i ++)
            cin>>a[i],b[i] = a[i];
        int minn = 1;
        int maxx = 1;
        sort(b,b+n);
        b[0] -= 1;
        mp[b[0]] = 1;
        for(int i = 1; i < n ; i ++){
            if(!mp[b[i]-1]){
                b[i] -= 1;
            }
            else if(!mp[b[i]]){
                ;
            }else if(!mp[b[i]+1]){
                b[i]+=1;
            }
            mp[b[i]] = 1;
        }
        sort(b,b+n);
        for(int i = 1 ; i < n ; i ++){
            if(b[i] != b[i-1]) maxx++;
        }
        int cnt = 0;
        for(int i = 0 ; i < n ; i ++){
            if(i == 0 || a[i] != b[cnt-1])
            b[cnt++] = a[i];
        }
        n = cnt;
        sort(b,b+n);
        b[0] += 1;
        for(int i = 1 ; i < n ; i ++){
            if(b[i]-1 == b[i-1]) b[i] -= 1;
            else if(b[i] != b[i-1]) b[i] += 1;
        }
        for(int i = 1 ; i < n ; i ++){
            if(b[i] != b[i-1]) minn++;
        }
        cout<<minn<<" "<<maxx<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值