zoukankan      html  css  js  c++  java
  • CF-822C Hacker, pack your bags! 思维题

    题目大意是给若干线段及其费用,每个线段权值即为其长度。要求找出两个不重合线段,令其权值和等于x且费用最少。

    解法:

    先分析一下题目,要处理不重合的问题,有重合的线段不能组合,其次这是一个选二问题,当枚举其中一条线段时,另一条合法线段的必要条件“权值”可以直接得出。

    对于第一个问题,想到先对线段根据l进行排序,这样每次枚举一个线段的时候,如果在它的l之后有一个合法线段,我们只要标记一下x-LenNow,待枚举到那个合法线段的时候自然就判断出来了。如果在它之前有一个合法线段符合条件,根据刚刚的做法我们自然可以处理。现在问题就是,万一它不合法,它重合呢?解决方法就是延迟标记它。对于线段们,我们已经对l排序,那么一旦枚举到一条线段的l大于等于之前待标记的某线段的r,那它及之后的线段都不会与它重合,而之前的线段(标记线段之后的线段)一定与它重合。所以我们维护一个优先队列,以待标记的r进行排序,每次枚举前,根据枚举到线段的l将部分待标记物执行标记即可。

    撤了那么多,看看代码吧。

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <queue>
    #define LL long long int
    using namespace std;
    struct node
    {
        LL r,len,c;
        friend bool operator < (node a,node b)
        {
            return a.r>b.r;
    
        }
    };//用于延迟标记
    struct cd
    {
        LL l,r,c;
    };
    LL mi[200005];
    const LL inf=3000000000;
    vector<cd> v;
    bool cmp(cd a,cd b)
    {
        if(a.l==b.l)
            return a.r<b.r;
        return a.l<b.l;
    }
    int main()
    {
        LL n,x;
        while(cin>>n>>x)
        {
            LL a,b,c;
            LL ans=inf;
            v.clear();
            fill(mi,mi+200000,inf);
            priority_queue<node> upt;
            for(LL i=0;i<n;i++)
            {
                cin>>a>>b>>c;
                v.push_back((cd){a,b,c});
            }
            sort(v.begin(),v.end(),cmp);
            for(int i=0;i<v.size();i++)
            {
                while(!upt.empty())
                {
                    node check=upt.top();
                    if(v[i].l<=check.r) break;
                    upt.pop();
                    if(mi[check.len]>check.c)
                        mi[check.len]=check.c;
                }
                cd now=v[i];
                LL len=now.r-now.l+1;
                LL f=x-len;
                upt.push((node){now.r,len,now.c});
                if(f<=0) continue;
                if(now.c+mi[f]<ans) ans=now.c+mi[f];
            }
            if(ans!=inf)
                cout<<ans<<endl;
            else
                cout<<-1<<endl;
        }
        return 0;
    }
  • 相关阅读:
    智能指针
    C++学习之对类中的成员函数的定义和声明最后添加一个const作用
    动态链接,静态链接库
    Java 位运算
    Java 工具类
    Java 枚举
    Java 内部类
    Java 异常机制
    Java hashCode 和 equals
    Java 字节流和字符流
  • 原文地址:https://www.cnblogs.com/LukeStepByStep/p/7156026.html
Copyright © 2011-2022 走看看