[JSOI2007]建筑抢修 [USACO09OPEN]Work Scheduling G ###K ###K ###K ###K //K
题目链接:https://www.luogu.com.cn/problem/P4053
题目链接:https://www.luogu.com.cn/problem/P2949
思路:考虑从截止时间短的来取 但这样取会发现如果有一段时间太长
可能会导致后面取的失去机会。那么就考虑如果前面的长 后面短的是否有机会替换掉他。
假设当前这个i 能够修好 那么就修 假设不能修好 和前面最长的一段比较,如果比他短 那么说明
可以不修前面那一段最长的 而修这一段 这样可以让后面的可选择的更多 因为是一直在维护一个最大值
那么用优先队列来维护 时间复杂度o(nlogn)
其实这是 贪心中的经典的后悔法 按照能选先选 后面的更优的代替前面的即可
一般做法是 排序 一个值 来确定顺序后 加优先队列来维护 后悔操作
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pi pair<int,int> 5 #define pb push_back 6 #define fi first 7 #define sc second 8 #define ull unsigned long long 9 const int maxn=2e5+10; 10 const int mod=1e9+7; 11 12 13 struct ac 14 { 15 int s,t; 16 bool operator<(ac a) 17 { 18 return t<a.t; 19 } 20 }; 21 ac a[maxn]; 22 23 int main() 24 { 25 ios::sync_with_stdio(0); 26 cin.tie(0); 27 cout.tie(0); 28 int n; 29 cin>>n; 30 for(int i=1;i<=n;i++) cin>>a[i].s>>a[i].t; 31 sort(a+1,a+1+n); 32 priority_queue<int>q; 33 ll sum=0; 34 for(int i=1;i<=n;i++) 35 { 36 q.push(a[i].s); 37 sum+=a[i].s; 38 while(sum>a[i].t) 39 { 40 sum-=q.top(); 41 q.pop(); 42 } 43 } 44 cout<<q.size()<<'\n'; 45 46 }
另外一道 也是后悔法
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 struct ac 8 { 9 int d,p; 10 bool operator<(ac a) 11 { 12 return d<a.d; 13 } 14 }; 15 ac a[maxn]; 16 17 struct bc 18 { 19 int v; 20 bool operator<(bc a)const 21 { 22 return v>a.v; 23 } 24 }; 25 26 int main() 27 { 28 ios::sync_with_stdio(false); 29 cin.tie(0); 30 int n; 31 cin>>n; 32 for(int i=1;i<=n;i++) 33 { 34 cin>>a[i].d>>a[i].p; 35 } 36 sort(a+1,a+1+n); 37 priority_queue<bc>q; 38 ll ans=0; 39 int now=0; 40 for(int i=1;i<=n;i++) 41 { 42 if(now+1<=a[i].d) 43 { 44 ans+=a[i].p; 45 now++; 46 q.push({a[i].p}); 47 } 48 else 49 { 50 if(q.top().v<=a[i].p) 51 { 52 ans-=q.top().v; 53 q.pop(); 54 ans+=a[i].p; 55 q.push({a[i].p}); 56 } 57 } 58 } 59 cout<<ans<<'\n'; 60 61 62 }

浙公网安备 33010602011771号