• UESTC 1558 Charitable Exchange


    UESTC_1558

        如果这个题目不考虑t而是改成问最少的转换次数,那么我们只要每次让它转换得越大越好,因此就可以将所有的exchange按r进行排序,每一次在一定的范围内选出v最大的exchange即可(这一点可以用堆来实现)。

        而现在是需要考虑t的,显然就不能直接贪心了,于是我们不妨往dp的角度上想一下。如果dp的话,那么就涉及到一个顺序的问题,按我们上面的思路将r排序后进行dp是否可行呢?是可以的,不妨假设y.r>=x.r且 y能够更新x,而由于y.r>=x.r,那么更新y的那个点就一定也可以更新x,而这样是比用y去更新x更优的。因此,如果我们将exchange按r排序后,后面的点是不会作为更新前面的点的决策的。

        接下来还有一个问题,就是我们如何去选择决策点呢,也就是说对于当前这个点i,我们选择前面的哪个点j来更新i?显然f[j](用到第j个exchange时花费的最小时间)越小越好,但前面拥有最小的f[j]的这个点j是否一定符合要求呢?不一定,因为有可能j.v<i.r。这样我们再联想到选择最小的f[j]是用堆(这里我是用线段树实现的堆)来实现的,那么如果j.v<i.r我们就将其从堆中删除,直到遇到j.v>=i.r的j,这样是否可以呢?其实究竟可不可以是取决于我们当前删除的j还是否可能做为更新后续一些比i大的点的决策,这显然是不会的,因为我们是按r将点排序的,如果j.v<i.r,那么j.v一定小于后续所有点的r。

        这样用线段树+dp的这个算法的可行性就讨论完了,最后再顺便说一下,我一开始写的时候结构体排序使用的是qsort,结果发现一直RE(只剩下了读入数据和排序的部分,其余部分全注释掉了),于是就想到不妨换一下sort试试,从队友那学完sort之后一交竟然真的AC了……难道这个题目对qsort有歧视……

    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include<algorithm>
    #define MAXD 100010
    #define INF 0x3f3f3f3f3f3f3f3fll
    using namespace std;
    int N, M, minf[4 * MAXD];
    long long f[MAXD];
    struct Ex
    {
        int v, r, t;
        bool operator < (const Ex &x) const
        {
            return r < x.r;
        }
    }ex[MAXD];
    void update(int cur)
    {
        int ls = cur << 1, rs = cur << 1 | 1;
        minf[cur] = f[minf[ls]] < f[minf[rs]] ? minf[ls] : minf[rs];
    }
    void build(int cur, int x, int y)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
        minf[cur] = 0;
        if(x == y)
        {
            f[x] = INF;
            return ;
        }
        build(ls, x, mid);
        build(rs, mid + 1, y);
    }
    void refresh(int cur, int x, int y, int k, int op)
    {
        int mid = (x + y) >> 1, ls = cur << 1, rs = cur << 1 | 1;
        if(x == y)
        {
            minf[cur] = (op ? k : 0);
            return ;
        }
        if(k <= mid)
            refresh(ls, x, mid, k, op);
        else
            refresh(rs, mid + 1, y, k, op);
        update(cur);
    }
    void init()
    {
        int i;
        scanf("%d%d", &N, &M);
        ++ N;
        ex[1].v = 1, ex[1].r = ex[1].t = 0;
        for(i = 2; i <= N; i ++)
            scanf("%d%d%d", &ex[i].v, &ex[i].r, &ex[i].t);
        sort(ex + 1, ex + 1 + N);
        build(1, 1, N);
        f[0] = INF, f[1] = 0;
        refresh(1, 1, N, 1, 1);
    }
    void solve()
    {
        int i, j, k;
        long long ans = INF;
        for(i = 2; i <= N; i ++)
        {
            while((k = minf[1]) && ex[k].v < ex[i].r)
                refresh(1, 1, N, k, 0);
            if(k == 0)
                break;
            f[i] = f[k] + ex[i].t;
            refresh(1, 1, N, i, 1);
        }
        for(i = 1; i <= N; i ++)
            if(ex[i].v >= M && f[i] < ans)
                ans = f[i];
        printf("%lld\n", ans == INF ? -1ll : ans);
    }
    int main()
    {
        int t, tt;
        scanf("%d", &t);
        for(tt = 0; tt < t; tt ++)
        {
            init();
            printf("Case #%d: ", tt + 1);
            solve();
        }
        return 0;
    }
  • 相关阅读:
    strncpy (Strings) – C 中文开发手册
    HTML track label 属性
    Java面试题:常用的Web服务器有哪些?
    鲲鹏920上安装ovs
    基于AC控制器+VXLAN解决方案
    二层MAC学习及BUM报文转发
    基于mac表的vxlan转发
    Agile Controller vxlan
    设置鲲鹏916/920通过pxe安装os
    ovs-vxlan&vlan
  • 原文地址:https://www.cnblogs.com/staginner/p/2495619.html
Copyright © 2020-2023  润新知