CF822C Hacker, pack your bags! 【思维好题】

来源:互联网 发布:windows bat日期加减 编辑:程序博客网 时间:2024/06/16 15:32

传送门
题意 :给你n段线, 每一段线有一个权值, 在这些线段中选取一些端点不重合的线, 他们的长度刚好是m, 这些线的对应权值要尽可能的小, 输出最小值.
//思路:一看范围最大复杂度不超过nlogn, 就是一个排序的复杂度, 所以做法就是先将所给的区间复制一份, 一份以L排序, 一份以R排序, 一起遍历一遍, 遍历的是点, 维护一个区间最小值, 和答案最优值, 当遇到左区间时, 查看len值是否小于m,且对应的区间sum[m-len]是否有值(即被更新过),此时就更新ans取较小的那个. 当遇到右端点, 直接更新sum[len]的值. 最后判一下ans的值就行了. 因为每次是遇到左端点才更新的ans, 所以可以保证区间没有相交.

AC Code //注意要爆int.

/** @Cain*/const int maxn=2e5+5;ll sum[maxn];struct node{    int l,r;    ll val;}s1[maxn],s2[maxn];bool cmp1(node a, node b){    return a.l<b.l;}bool cmp2(node a,node b){    return a.r<b.r;}void solve(){    int n,x;    scanf("%d%d",&n,&x);    for(int i=0;i<n;i++){        scanf("%d%d%I64d",&s1[i].l,&s1[i].r,&s1[i].val);        s2[i].l = s1[i].l; s2[i].r = s1[i].r; s2[i].val = s1[i].val;    }    sort(s1,s1+n,cmp1);    sort(s2,s2+n,cmp2);    ll ans = INF;    //这个长度为x时的最优答案值.    for(int i=0;i<=maxn;i++)        sum[i] = INF;    int k1 = 0,k2 = 0;    for(int i=1;i<=maxn;i++){        while(s1[k1].l == i){            int len = s1[k1].r - s1[k1].l + 1 ;            if(len < x && sum[x-len] != INF)                ans = min(ans,s1[k1].val+sum[x-len]);            k1++;        }        while(s2[k2].r == i){            int len = s2[k2].r - s2[k2].l + 1 ;            sum[len] = min(sum[len],s2[k2].val);            k2++;        }    }    if(ans == INF)        printf("-1\n");    else        printf("%I64d\n",ans);}int main(){    int t = 1 ;    //scanf("%d",&t);    while(t--){    //    printf("Case %d: ", cas++);        solve();        //printf("\n");    }}
原创粉丝点击