codeforces433DIV2.(Sep 7th 2017)

Problem A.Fraction

签到题,给出一个数n,求a,b使得a+b=n且(a,b)=1(a

Problem B.Maxim Buys an Apartment

签到题,但是有部分细节需要注意。题意:有一排并列的房子,总共有n间,然后当前已经有k间房子被别人住了,现在有个人要搬进去住,这个人喜欢热闹(我不喜欢)他要住一间旁边有人住的房子,问对于k间房已经有人住的情况下,他最少,最多有几间房可以选择。 1<=n<=109,0<=k<=n
题解:显然k间房放到一边的时候最小,就一间可以选。然后考虑,当K比较小的时候,一间房子可以管左边右边两个房子,k个房子最多管 k2 个房子,然后又有k个房子被占,所以总共 k3 个房子,比较 k3 和n的大小即可,如果小,最多 k2 ,否则 nk 个。最后注意k=0的情况和n=k的情况。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
#include<queue>
using namespace std;
long long n, k;
int main()
{
    scanf("%lld%lld", &n, &k);
    long long minn = 1;
    if (n == k || k == 0) minn = 0;
    long long maxx = 0;
    if (k == 0)
    {
        maxx = 0;
    }
    else if (k*3 <= n)
    {
        maxx = 2 * k;
    }
    else
    {
        maxx = n-k;
    }
    printf("%lld %lld\n", minn, maxx);
    return 0;
}

Problem C.Planning

这个题题意大概是调度航班问题,然后有n个航班,一开始第i个航班就是在时间i起飞,k表示延误了现在的时间k,从k时间开始往后航班才能起飞,然后每个单位时间起飞一个航班,每个航班有一个延误的代价 Ci ,然后对于一个调度来说有一个代价 cost=(tii)Ci ,而 ti>=i ,因为显然航班不会提前飞。
题解:此题可以考虑贪心,显然我希望代价大的航班越准时越好,排个序,具体看代码。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxn = 600100;
long long  n, k;
struct fight{
    long long v;
    int id;
    int ans;
}c[maxn];
bool p[maxn];
int cmp(fight x, fight y)
{
    if (x.v != y.v)
        return x.v > y.v;
    return x.id < y.id;
}
int cmpid(fight x, fight y)
{
    return x.id < y.id;
}
int main()
{
    scanf("%lld%lld", &n, &k);
    for (int i = 1 ; i <= n; ++i)
    {
        scanf("%lld", &c[i].v);
        c[i].id = i;
    }
    sort(c+1, c+n+1, cmp);
    int po = 1;
    for (int i = 1; i <= n; ++i)
    {
        while (p[po+k]) ++po;
        if (c[i].id > po+k && p[c[i].id] == 0)
        {
            p[c[i].id] = 1;
            c[i].ans = c[i].id;
        }
        else
        {
            p[po+k] = 1;
            c[i].ans = po+k;
            po++;
        }
    }
    long long sum = 0;

    sort(c+1, c+n+1, cmpid);
     for (int i = 1; i <= n; ++i)
        sum += (c[i].ans-i)*c[i].v;
    printf("%lld\n", sum);
    for (int i = 1; i < n; ++i)
        printf("%d ", c[i].ans);
    printf("%d\n", c[n].ans);
    return 0;
}

Problem D.Jury Meeting

哎,比赛的时候看题太慢,最后没时间仔细想清楚题,也没时间写了,感觉自己还需要加快速度吧。其实打完后发现这题也是个傻逼题。题意大概就是告诉你有n+1个城市,编号1-n的每个城市都有个陪审员,要飞到城市0,然后再飞回原来的城市,先给出了 n,m,k n 表示除0城市外有n个城市,m表示有 m 张机票,k表示这 n 个人要在0城市一起工作k天。这 m <script type="math/tex" id="MathJax-Element-1941">m</script>张机票由m列给出,分别四个参数,d,f,t,c,分别表示机票时间,从f飞到t,花费为c(f和t中至少有个一个为0),然后问使得这n个人能在0城市一起待k天的情况下,机票最小花费。(飞机飞到的那天和离开的那天,不能算在一起工作)
题解:考虑k的范围为1e6,可以考虑枚举t表示他们第一天一起开始工作是哪天,即这n个人是一起飞到了0城市,那么第t天之前的机票我显然都买好,且买最便宜的,这可以确定,预处理维护前缀和即可(同时要判断n个人的机票都买了),而他们走的那天显然就是第t+k+1天,这天之后的那些返程机票我显然也能确定,取最便宜的,即预处理维护后缀和(同理,n个人的机票都要买了)。然后扫一遍取最小就可以啦。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxn = 100100;
int n, m, k, lx, rx, minn;
struct ticket{
    long long d, f, t, c;
}v[maxn];
long long pre[maxn*10], suf[maxn*10], prem[maxn], sufm[maxn];
int cmp(ticket x, ticket y)
{
    return x.d < y.d;
}
void init()
{
    int mark1 = 0, mark2 = 0;
    int j = 1;
    for (int i = 1; i <= minn; ++i)
    {
        pre[i] = pre[i-1];
        while (i == v[j].d)
        if (v[j].f != 0 && j <= m)
        {
            if (prem[v[j].f] == 0)
            {
                prem[v[j].f] = v[j].c;
                pre[v[j].d] += v[j].c;
                ++mark1;
                if (mark1 == n && lx > i) lx = i;
            }
            else if (v[j].c < prem[v[j].f])
            {
                pre[v[j].d] += v[j].c-prem[v[j].f];
                prem[v[j].f] = v[j].c;
            }
            ++j;

        }
        else ++j;

    }
    j = m;
    for (int i = minn; i >= 1; --i)
    {
        suf[i] = suf[i+1];
        while (i == v[j].d)
        if (v[j].t != 0 && j > 0)
        {
            if (sufm[v[j].t] == 0)
            {
                sufm[v[j].t] = v[j].c;
                suf[v[j].d] += v[j].c;
                ++mark2;
                if (mark2 == n && rx < i) rx = i;
            }
            else if (v[j].c < sufm[v[j].t])
            {
                suf[v[j].d] += v[j].c-sufm[v[j].t];
                sufm[v[j].t] = v[j].c;
            }
            --j;
        }
        else --j;

    }
}
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    for (int i = 1; i <= m; ++i)
    {
        scanf("%lld%lld%lld%lld", &v[i].d, &v[i].f, &v[i].t, &v[i].c);
        if (v[i].d > minn) minn = v[i].d;
    }
    lx = minn, rx = 1;
    sort(v+1, v+m+1, cmp);
    init();
    long long ans = 1e18;
    for (int i = lx; i < rx-k; ++i)
        if (pre[i]+suf[i+k+1] < ans) ans = pre[i]+suf[i+k+1];
    /*for (int i = 1; i <= minn; ++i)
        printf("%d ", pre[i]);
    printf("\n");
    for (int i = 1; i <= minn; ++i)
        printf("%d ", suf[i]);
    printf("\n");
    printf("%d %d\n", lx,rx);*/
    if (rx - lx > k) printf("%lld\n", ans);
        else printf("-1\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值