题解

3 条题解

  • 1
    @ 2025-06-18 14:26:31
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    
    using namespace std;
    
    const ll INF=1e18;
    const int N=100005;
    int n,m,cnt,nn;
    struct po{
        int l,r,v;
    };
    po a[N];
    int X[N<<1];
    struct node{
        ll mn;
    };
    node t[N<<2];
    
    int cmp(const po &A,const po &B) {return A.r<B.r;}
    
    void build(int bh,int l,int r)
    {
        if (l!=1) t[bh].mn=INF;
        else t[bh].mn=0;
        if (l==r) return;
        int mid=(l+r)>>1;
        build(bh<<1,l,mid);
        build(bh<<1|1,mid+1,r);
    }
    
    void insert(int bh,int l,int r,int x,ll z)
    {
        if (l==r)
        {
            t[bh].mn=min(t[bh].mn,z);
            return;
        }
        int mid=(l+r)>>1;
        if (x<=mid) insert(bh<<1,l,mid,x,z);
        else insert(bh<<1|1,mid+1,r,x,z);
        t[bh].mn=min(t[bh<<1].mn,t[bh<<1|1].mn);
    }
    
    ll ask(int bh,int l,int r,int L,int R)
    {
        if (l>=L&&r<=R) return t[bh].mn;
        ll ans=INF;
        int mid=(l+r)>>1;
        if (L<=mid) ans=min(ans,ask(bh<<1,l,mid,L,R));
        if (R>mid) ans=min(ans,ask(bh<<1|1,mid+1,r,L,R));
        return ans;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        for (int cas=1;cas<=T;cas++)
        {
            scanf("%d%d",&n,&m);
            cnt=0; nn=0;
            for (int i=1;i<=n;i++) 
            {
                cnt++;
                scanf("%d%d%d",&a[i].r,&a[i].l,&a[i].v);
                if (a[i].l>a[i].r) cnt--;
                else X[++nn]=a[i].r;
            }
    
            X[++nn]=1;                            //dp初始值 
            sort(X+1,X+1+nn);
            nn=unique(X+1,X+1+nn)-X-1;
            build(1,1,nn);
    
            sort(a+1,a+1+cnt,cmp);
            for (int i=1;i<=cnt;i++)
            {
                int x=lower_bound(X+1,X+1+nn,a[i].l)-X;
                int y=lower_bound(X+1,X+1+nn,a[i].r)-X;
                ll minn=ask(1,1,nn,x,y);
                if (minn!=INF)
                    insert(1,1,nn,y,minn+(ll)a[i].v);
            }
    
            printf("Case #%d: ",cas);
            ll ans=ask(1,1,nn,lower_bound(X+1,X+1+nn,m)-X,nn);
            if (ans!=INF) printf("%d\n",ans);
            else printf("-1\n");
        } 
        return 0;
    }
    
  • 1
    @ 2014-11-02 15:47:32

    对于这个题目, 因为要离散化, 所以有些c++选手会使用stl, 这会让程序变得非常慢. 希望慎用.

  • 1
    @ 2014-11-02 14:16:10
    • @ 2014-11-08 00:37:41

      我们发现永远不可能在交换后钱变少了,于是我们可以把所有操作按照V的大小 升序排列。如果我们要执行这一交换,必然是为了得到Vi的钱,而我们只能从\(R_i\)~\(V_{i-1}\)转移得到。用动态规划实现,F(i)表示得到i元钱需要的最少时间。最后我们只需要先离散,然后用线段树维护区间最值即可,时间复杂度O(NlogN)。

  • 1

信息

ID
1901
难度
8
分类
(无)
标签
(无)
递交数
513
已通过
48
通过率
9%
被复制
3
上传者