zoukankan      html  css  js  c++  java
  • FJUT2019暑假第二次周赛 A题

    A题

    题目链接

    服务器维护
    TimeLimit:1500MS MemoryLimit:128MB
    64-bit integer IO format:%lld
    Problem Description
    Dsc最大的梦想就是有一款属于自己的游戏(不可能的),可以把自己的奇思妙想在虚拟的世界中创造出来,假设Dsc成功了,创造出了一款网游(小作坊的那种),现在为了节省成本,Dsc决定自己维护服务器健康,但总会有没时间的时候。

    假设从S分钟开始,E分钟结束[S,E]这段时间Dsc是没有时间的,这时候Dsc需要找人来维护服务器,当然是有偿的。在[S,E]这段时间中有n个人有空余时间(不一定是全部[S,E])第i个人在ai,bi这段时间有空,共需要ci的管理费。

    现在请帮Dsc算一算,在他没空的时间内[S,E],每天都至少有一个人在管理服务器所需要的最少花费是多少,如果没有任何方案使[S,E]时间内每天都至少有一个人在管理服务器则输出-1;

    Input
    第一行为三个整数n,S,E分别表示有n个人有空,在[S,E]时间内Dsc没空

    接下来有n行,每行3个整数ai,bi,ci分别表示第i个人在[ai,bi]时间内有空,雇佣共需要ci管理费

    1<=n<=1e5

    0<=S<=E<=1e5

    S<=ai<=bi<=E

    1<=ci<=1e5

    Output
    Dsc在没空的时间找人管理服务器所需的最少花费,没有方案则输出-1

    SampleInput
    3 2 4
    2 3 2
    4 4 1
    2 4 4
    SampleOutput
    3

    [思路1]:

    其实这个题目就是一个DP加上线段树维护即可AC, 根据题意容易得知,需要区间全覆盖,那么我们可以考虑先按L从小到大排序维护从[S, R]所花费的最小价值,可得状态为dp[i]代表从[s, i]区间覆盖的最小价值。
    可得状态转移方程为
    dp[i] = min(dp[i], quert_min(l - 1, i - 1)) + w)
    即可AC
    

    附上代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const int MAXN = 1e5 + 15;
    const LL inf = __LONG_LONG_MAX__;
    int n, s, e;
    struct Segtree{
        LL arr[MAXN];
        struct NODE{
            int l, r;
            LL mins;
        }tree[MAXN << 2];
        void build(int root, int l, int r){
            tree[root].l = l, tree[root].r = r;
            if(l == r){
                tree[root].mins = arr[l];
                return ;
            }
            int mid = (l + r) >> 1;
            build(root << 1, l, mid);
            build(root << 1 | 1, mid + 1, r);
            tree[root].mins = min(tree[root << 1].mins, tree[root << 1 | 1].mins);
            return ;
        }
        void update(int root, int num, LL val){
            if(tree[root].l == num && tree[root].r == num){
                tree[root].mins = val;
                return ;
            }
            int mid = (tree[root].l + tree[root].r) >> 1;
            if(num <= mid){
                update(root << 1, num, val);
            }
            else{
                update(root << 1 | 1, num, val);
            }
            tree[root].mins = min(tree[root << 1].mins, tree[root << 1 | 1].mins);
            return ;
        }
        LL query(int root, int l, int r){
            if(tree[root].l >= l && tree[root].r <= r){
                return tree[root].mins;
            }
            int mid = (tree[root].l + tree[root].r) >> 1;
            if(r <= mid){
                return query(root << 1, l, r);
            }
            else if(l > mid){
                return query(root << 1 | 1, l, r);
            }
            else{
                return min(query(root << 1, l, mid), query(root << 1 | 1, mid + 1, r));
            }
        }
    }seg;
    struct Person{
        int l, r;
        LL value;
        friend bool operator< (const Person &a, const Person &b){
            if(a.l == b.l){
                return a.value < b.value;
            }
            else{
                return a.l < b.l;
            }
        }
    }arr[MAXN];
    LL dp[MAXN];
    int main(){
        ios::sync_with_stdio(false);
        cin >> n >> s >> e;
        s += 2, e += 2;
        for(int i = 0; i < n; i ++){
            cin >> arr[i].l >> arr[i].r >> arr[i].value;
            arr[i].l += 2, arr[i].r += 2;
        }
        for(int i = s; i <= e; i ++){
            seg.arr[i] = inf;
            dp[i] = inf;
        }
        for(int i = 0; i < s; i ++){
            seg.arr[i] = 0;
            dp[i] = 0;
        }
        seg.build(1, 1, e);
        sort(arr, arr + n);
        for(int i = 0; i < n; i ++){
            if(seg.query(1, arr[i].l - 1, arr[i].r - 1) != inf){
                dp[arr[i].r] = min(dp[arr[i].r], seg.query(1, arr[i].l - 1, arr[i].r - 1) + arr[i].value);
                seg.update(1, arr[i].r, dp[arr[i].r]);    
            }
        }
        if(dp[e] == inf){
            cout << "-1
    ";
        }
        else{
            cout << dp[e] << endl;
        }
        return 0;
    }
    

    [思路2]:

    对于整个数据进行建图,将区间能互相覆盖的点连接起来,然后跑最短路径
    

    附上代码:

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <cctype>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <list>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <algorithm>
    #include <functional>
    #define lowbit(x) (x&(-x))
    #define rep(i,a,n) for (int i=a;i<=n;i++)
    #define per(i,a,n) for (int i=a;i>=n;i--)
    #define mem(ar,num) memset(ar,num,sizeof(ar))
    #define debug(x) cout << #x << ": " << x << endl
    using namespace std;
    typedef long long LL;
    typedef unsigned long long ULL;
    const int    prime = 999983;
    const int    INF = 0x7FFFFFFF;
    const LL     INFF =0x7FFFFFFFFFFFFFFF;
    const double pi = acos(-1.0);
    const double inf = 1e18;
    const double eps = 1e-6;
    const LL     mod = 1e9 + 7;
    const int    maxn = 1e6 + 7;
    const int    maxm = 4e6 + 7;
    
    int n, m, first[maxn], sign;
    
    struct Edge{
        int to, w, next;
    }edge[maxn * 2];
    
    void init(){
        for(int i = 0; i <= n; i++){
            first[i] = -1;
        }
        sign = 0;
    }
    
    void addEdge(int u,int v,int w){
        edge[sign].to = v;
        edge[sign].w = w;
        edge[sign].next = first[u];
        first[u] = sign++;
    }
    
    struct Node{
        int to;
        LL cost;
        Node(){}
        Node(int tt, LL cc):to(tt),cost(cc){}
        friend bool operator < (const Node &a, const Node &b){
            return a.cost > b.cost;
        }
    };
    
    LL dist[maxn];
    int vis[maxn];
    
    LL dijkstra(int s, int t){
        for(int i = 0; i <= n; i++){
            dist[i] = INFF;
            vis[i] = 0;
        }
        priority_queue<Node> que;
        que.push(Node(s,0));
        while(!que.empty())
        {
            Node now = que.top();
            //printf("%d
    ",now.to);
            que.pop();
            if(!vis[now.to]){
                vis[now.to] = 1;
                dist[now.to] = now.cost;
                for(int i = first[now.to];~i;i = edge[i].next){
                    int to = edge[i].to;
                    LL w = edge[i].w;
                    if(!vis[to]){
                        que.push(Node(to,now.cost + w));
                    }
                }
            }
        }
        return dist[t] == INFF ? -1 : dist[t];
    }
    int main()
    {
            int s, t;
            scanf("%d%d%d",&m,&s,&t);
            n = t + 1;
            init();
            for(int i = 1; i<= m; i++){
               int u, v, w;
               scanf("%d%d%d",&u,&v,&w);
               addEdge(u,v + 1,w);
            }
            for(int i = s + 1; i <= n; i++){
                addEdge(i ,i - 1, 0);
            }
            printf("%lld
    ",dijkstra(s, t+1));
        return 0;
    }
    
  • 相关阅读:
    如何计算两个日期之间相差天数
    解决并发问题的小技巧
    Linq实现下拉框绑定
    No DataType in DataTemplate in Windows Phone(二)
    使用TOAD操作oracle初步
    使用log4net记录server Log
    尘世一场烟火
    No DataType in DataTemplate in Windows Phone(—)
    MVC设置初始页时发生的无法找到资源的简单错误
    oracle 使用in的灵异事件
  • 原文地址:https://www.cnblogs.com/qq136155330/p/11328366.html
Copyright © 2011-2022 走看看