Codeforces Round #611 (Div. 3)

40 篇文章 0 订阅
38 篇文章 0 订阅

A Minutes Before the New Year

不用写 f o r for for循环,直接用 1440 1440 1440减去当前分钟数就行了

T = int(input())
for kase in range(T):
    h, m = [int(x) for x in input().split()]
    print(1440-h*60-m)

B Candies Division

T = int(input())
for kase in range(T):
    n, k = [int(x) for x in input().split()]
    ans = n//k*k
    ans += min(n%k,k//2)
    print(ans)

C Friends and Gifts

这题是要在给定的图上连一些边使其形成一个置换,且 f i ≠ i f_i \neq i fi=i

先统计一下入度,剩下的边必须连到入读为 0 0 0的点上去

先给那些既没有入度也没有出度的点安排出度,这样是为了防止最后出现他不得不连自己的情况,搞一个双端队列就可以维护了。

然后再安排剩下的就好了

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll f[maxn], n, ok[maxn];
deque<ll> q;
int main()
{
    ll i;
    n=read();
    rep(i,n)f[i]=read(), ok[f[i]]=1;
    rep(i,n)if(!ok[i])q.emb(i);
    rep(i,n)if(!f[i] and !ok[i])
    {
        if(q.front()!=i){f[i]=q.front(); q.pop_front();}
        else {f[i]=q.back(); q.pop_back();}
    }
    rep(i,n)if(!f[i])
    {
        if(q.front()!=i){f[i]=q.front(); q.pop_front();}
        else {f[i]=q.back(); q.pop_back();}
    }
    rep(i,n)printf("%lld ",f[i]);
    return 0;
}

D Christmas Trees

一个 b f s bfs bfs

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
priority_queue<pll,vector<pll>,greater<pll>> heap;
set<ll> used;
ll n, m;
vector<ll> ans;
bool in(ll x){return used.find(x)!=used.end();}
void ins(ll pos, ll step){if(!in(pos)) { heap.em( pll(step,pos) ); used.em(pos); } }
ll a[maxn];
int main()
{
    ll i, j, tot=0;
    n=read(), m=read();
    rep(i,n)used.em(a[i]=read());
    rep(i,n)ins(a[i]-1,1),ins(a[i]+1,1);
    while(m--)
    {
        auto pr=heap.top(); heap.pop();
        auto pos=pr.second, step=pr.first;
        tot += pr.first;
        ans.emb(pos);
        ins(pos-1,step+1);
        ins(pos+1,step+1);
    }
    printf("%lld\n",tot);
    for(auto x:ans)printf("%lld ",x);
    return 0;
}

E New Year Parties

这题好

对于最小值,想法肯定是尽量去“缩”,能合并的就合并。令 c i c_i ci表示 i i i处有多少个人,我从小到大枚举 i i i,当我发现第一个 c i ≠ 0 c_i \neq 0 ci=0时,我就把 c i c_i ci的人都赶到 c i + 1 c_{i+1} ci+1去,这样肯定不会更劣嘛,而且增加了与右边的人的接触机会。当我这样决策时,其实就认定了 i + 1 i+1 i+1必定有人,那么既然这里已经有人了,我就破罐子破摔,右边有人的话让他也过来,就这样贪心下去…得到最小的答案

对于最大值,想法是尽量去“扩”,我先从左往右扫,让那些能放一个人去左边的就放一个人去左边。然后再反过来,从右往左扫,让能去右边的就去右边。

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
ll n, a[maxn], b[maxn];
int main()
{
    ll i, ans1=0, ans2=0, len;
    n=read();
    rep(i,n)a[read()]++;
    rep(i,n)b[i]=a[i];
    len=0;
    rep(i,n)if(a[i])
    {
        ans1++;
        i++;
        if(a[i+1])i++;
    }
    printf("%lld ",ans1);
    for(i=0;i<=n;i++)if(b[i]==0 and b[i+1])b[i]++, b[i+1]--;
    for(i=n+1;i;i--)if(b[i]==0 and b[i-1])b[i]++, b[i-1]--;
    for(i=0;i<=n+1;i++)ans2+=!!b[i];
    printf("%lld",ans2);
    return 0;
}

F DIY Garland

i i i点到父亲的连边的权值是 2 i 2^i 2i+所有 i i i到儿子的边的权值,所以 i i i到父亲的这条边必然在子树中的边之前出现,再者,最开始走的边肯定都是带有 2 n 2^n 2n,直到我走完了所有带有 2 n 2^n 2n的边,才会去走 2 n − 1 2^{n-1} 2n1,看起来就是不停的走一些链。

走完一条链走下一条链,当且仅当我已经走到了当前最大的数字。所以出现重复元素,就说明上次走过去的那条边的末端是目前没出现的最大的数字。

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 1000010
#define maxe 1000010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{
    ll c, f(1);
    for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;
    for(;isdigit(c);c=getchar())x=x*10+c-0x30;
    return f*x;
}
vector<ll> v;
set<ll> s;
vector<pll> ans;
ll n, a[maxn], p;
bool used(ll x){return s.find(x)!=s.end();}
int no(){printf("-1");return 0;}
int main()
{
    ll i, r;
    n=read();
    rep(i,n-1)a[i]=read();
    rep(i,n)v.emb(i);
    rep(i,n-1)
    {
        ll x=a[i];
        if(used(x))
        {
            while(!v.empty() and used(v.back()))v.pop_back();
            if(v.empty())return no();
            auto t=v.back(); v.pop_back();
            s.em(t);
            ans.emb( pll(t,p) );
        }
        else
        {
            if(p)ans.emb( pll(p,x) );
            else r=x;
            s.em(x);
        }
        p=x;
    }
    while(!v.empty() and used(v.back()))v.pop_back();
    if(v.empty())return no();
    ans.emb( pll(v.back(),p) ); v.pop_back();
    while(!v.empty() and used(v.back()))v.pop_back();
    if(!v.empty())return no();
    printf("%lld\n",r);
    for(auto pr:ans)printf("%lld %lld\n",pr.first,pr.second);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值