Codeforces 822C Hacker, pack your bags!(思维)

题目大意:给你n个旅券,上面有开始时间l,结束时间r,和花费cost,要求选择两张时间不相交的旅券时间长度相加为x,且要求花费最少。

解题思路:看了大佬的才会写!其实和之前Codeforces 776C的写法有点像,遍历l,设以l为起始时间时长为time,看是否存在时长为x-time且与当前时段不相交的时间段,取最小值。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 using namespace std;
 6 const int N=2e5+5;
 7 typedef pair<int,int>pii;
 8 
 9 vector<pii>v[N];//存放拿来拼凑的区段
10 vector<pii>rc[N];//用来存放接下来要遍历的区段
11 int    mp[N];
12  
13 int main(){
14     ios::sync_with_stdio(false); 
15     int n,x;
16     cin>>n>>x;    
17     for(int i=1;i<=n;i++){
18         int l,r,cost;
19         cin>>l>>r>>cost;
20         //以l为索引存放区段 
21         rc[l].push_back(pii(r,cost));
22     }
23     int ans=2e9+1;
24     //遍历l的值 
25     for(int l=1;l<=2e5;l++){
26         for(int i=0;i<rc[l].size();i++){
27             int r=rc[l][i].first;
28             int cost=rc[l][i].second;
29             int time=r-l+1;
30             if(time>x)
31                 continue;
32             //看是否存在与这段时间相加和为x,且不想交的时段 
33             if(mp[x-time]){ 
34                 ans=min(ans,mp[x-time]+cost);
35             }
36             //遍历过的放到左边区域 
37             v[r].push_back(pii(time,cost));    
38         }
39         //找v[l],也就是左边区域的v[r],因为下一次l2=l+1,肯定大于r,所以区间不会相交,可以直接拿来用 
40         for(int i=0;i<v[l].size();i++){
41             int time=v[l][i].first;
42             int cost=v[l][i].second;
43             if(!mp[time]||mp[time]>cost)
44                 mp[time]=cost;    
45         }
46     }
47     if(ans==2e9+1)
48         cout<<-1<<endl;
49     else
50         cout<<ans<<endl;
51 } 
原文地址:https://www.cnblogs.com/fu3638/p/7111450.html