贪心 总结 ###K
总结acwing上的 贪心问题
记下结论即可
左端点升序应该对应右端点降序 左端点降序对应右端点升序
所以 只需要猜 左端点/ 右端点升序即可 而不用猜四种
1.区间选点问题,选最少的点使得每个区间至少包含一个点
思路:右端点升序排序,没有被覆盖的右端点全部选上
题目链接:https://www.acwing.com/problem/content/907/
题目链接:https://www.acwing.com/problem/content/114/ 可以将问题转换成区间选点问题, 只需要考虑每个岛能被覆盖的线段是那一段即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair<ll,ll> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 pi a[maxn]; 11 12 bool cmp(pi a,pi b) 13 { 14 return a.sc<b.sc; 15 } 16 17 18 int main() 19 { 20 ios::sync_with_stdio(0); 21 cin.tie(0); 22 int n; 23 cin>>n; 24 for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].sc; 25 sort(a+1,a+1+n,cmp); 26 int now=a[1].sc; 27 int ans=1; 28 for(int i=2;i<=n;i++) 29 { 30 if(a[i].fi<=now&&now<=a[i].sc) continue; 31 ans++; 32 now=a[i].sc; 33 } 34 cout<<ans<<'\n'; 35 36 37 38 39 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 const int mod=1e9+7; 5 const double eps=1e-9; 6 #define ll long long 7 #define pi pair<double,double> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 struct ac 13 { 14 double l,r; 15 bool operator<(ac a) 16 { 17 return r<a.r; 18 } 19 }; 20 ac a[maxn]; 21 22 23 24 int main() 25 { 26 ios::sync_with_stdio(0); 27 cin.tie(0); 28 int n,d; 29 cin>>n>>d; 30 int f=0; 31 int tot=0; 32 for(int i=1;i<=n;i++) 33 { 34 int x,y; 35 cin>>x>>y; 36 if(y>d) f=1; 37 double t=sqrt((double)d*d-y*y); 38 double l=-x-t,r=-x+t; 39 a[++tot]={l,r}; 40 } 41 if(f) 42 { 43 cout<<-1<<'\n'; 44 return 0; 45 } 46 sort(a+1,a+1+n); 47 int ans=1; 48 double now=a[1].r; 49 for(int i=2;i<=n;i++) 50 { 51 if(a[i].l<now+eps) continue; 52 ans++; 53 now=a[i].r; 54 } 55 cout<<ans<<'\n'; 56 57 58 59 60 61 }
或者 左端点降序排序 一直选左端点即可
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=1e5+10; 10 const int mod=1e9+7; 11 12 pi a[maxn]; 13 14 15 int main() 16 { 17 ios::sync_with_stdio(0); 18 cin.tie(0); 19 int n; 20 cin>>n; 21 for(int i=1;i<=n;i++) 22 { 23 cin>>a[i].fi>>a[i].sc; 24 } 25 sort(a+1,a+1+n); 26 reverse(a+1,a+1+n); 27 int ans=0; 28 int now=2e9; 29 for(int i=1;i<=n;i++) 30 { 31 if(now>=a[i].fi&&now<=a[i].sc) continue; 32 ans++; 33 now=a[i].fi; 34 } 35 cout<<ans<<'\n'; 36 37 38 39 40 41 }
2.最大不相交区间数量,问如何选择尽量多的区间,使得区间没有交集
思路:右端点升序排序, 当前的区间如果左端点大于右端点那么就选上,更新now (右端点)
题目链接:https://www.acwing.com/problem/content/910/
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair<int,int> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 pi a[maxn]; 11 12 bool cmp(pi a,pi b) 13 { 14 return a.sc<b.sc; 15 } 16 17 18 int main() 19 { 20 ios::sync_with_stdio(0); 21 cin.tie(0); 22 int n; 23 cin>>n; 24 for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].sc; 25 sort(a+1,a+1+n,cmp); 26 int now=a[1].sc; 27 int ans=1; 28 for(int i=2;i<=n;i++) 29 { 30 if(a[i].fi<=now) continue; 31 now=a[i].sc; 32 ans++; 33 } 34 cout<<ans<<'\n'; 35 36 37 38 39 }
或者左端点降序排序
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=1e5+10; 10 const int mod=1e9+7; 11 12 pi a[maxn]; 13 14 15 16 int main() 17 { 18 ios::sync_with_stdio(0); 19 cin.tie(0); 20 int n; 21 cin>>n; 22 for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].sc; 23 sort(a+1,a+1+n); 24 reverse(a+1,a+1+n); 25 int now=2e9; 26 int ans=0; 27 for(int i=1;i<=n;i++) 28 { 29 int l=a[i].fi,r=a[i].sc; 30 if(r<now) now=l,ans++; 31 } 32 cout<<ans<<'\n'; 33 34 35 36 37 38 39 }
3.区间分组问题,问如何将每个区间分组,使得每组区间内部两两没有交集
思路:以左端点升序排序,然后用小根堆维护每次区间的右端点的值,当前区间的左端点大于某一组中的最小值即可以划分进这一组
用小根堆维护最小值,每次可以放进新的组就删除再插入,否则只有插入 同理右端点降序排序也可以
题目链接:https://www.acwing.com/problem/content/description/908/
题目链接:https://www.acwing.com/problem/content/113/ 一样区间分组 不过多一个给每个区间编号
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair<int,int> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 struct ac 11 { 12 int l,r; 13 bool operator<(ac a) 14 { 15 return l<a.l; 16 } 17 }; 18 ac a[maxn]; 19 20 21 22 int main() 23 { 24 ios::sync_with_stdio(0); 25 cin.tie(0); 26 int n; 27 cin>>n; 28 for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r; 29 sort(a+1,a+1+n); 30 int ans=0; 31 priority_queue<pi>q; 32 for(int i=1;i<=n;i++) 33 { 34 int u=a[i].l; 35 if(!q.empty()&&q.top().sc<u) 36 { 37 q.pop(); 38 q.push({-a[i].r,a[i].r}); 39 continue; 40 } 41 q.push({-a[i].r,a[i].r}); 42 ans++; 43 } 44 cout<<ans<<'\n'; 45 46 47 48 49 50 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=5e4+10; 4 const int mod=1e9+7; 5 #define ll long long 6 #define pi pair<int,int> 7 #define fi first 8 #define sc second 9 #define pb push_back 10 struct ac 11 { 12 int v,p; 13 bool operator<(ac a)const 14 { 15 return v>a.v; 16 } 17 }; 18 int ans[maxn]; 19 20 struct bc 21 { 22 int l,r,p; 23 bool operator<(bc a) 24 { 25 return l<a.l; 26 } 27 }; 28 bc a[maxn]; 29 30 31 32 int main() 33 { 34 ios::sync_with_stdio(0); 35 cin.tie(0); 36 int n; 37 cin>>n; 38 priority_queue<ac>q; 39 for(int i=1;i<=n;i++) cin>>a[i].l>>a[i].r,a[i].p=i; 40 sort(a+1,a+1+n); 41 int tot=0; 42 for(int i=1;i<=n;i++) 43 { 44 int id=a[i].p; 45 if(!q.empty()&&q.top().v<a[i].l) 46 { 47 ac u=q.top(); 48 q.pop(); 49 ans[id]=u.p; 50 q.push({a[i].r,u.p}); 51 } 52 else 53 { 54 q.push({a[i].r,++tot}); 55 ans[id]=tot; 56 } 57 } 58 cout<<tot<<'\n'; 59 for(int i=1;i<=n;i++) 60 { 61 cout<<ans[i]<<'\n'; 62 } 63 64 65 66 67 }
4.区间覆盖问题 给定一段目标区间, 给定n个区间, 从n个区间中选最少的区间覆盖掉目标区间
思路:左端点升序排序 每次找包含当前st 的区间的右端点最大的,然后更新st为这个最大值继续找
题目链接:https://www.acwing.com/problem/content/909/
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=1e5+10; 10 const int mod=5000011; 11 12 13 pi a[maxn]; 14 int n; 15 int s,t; 16 17 18 19 int main() 20 { 21 ios::sync_with_stdio(0); 22 cin.tie(0); 23 cin>>s>>t; 24 cin>>n; 25 for(int i=1;i<=n;i++) cin>>a[i].fi>>a[i].sc; 26 sort(a+1,a+1+n); 27 int now=s; 28 int ans=0; 29 for(int i=1;i<=n;i++) 30 { 31 int j=i; 32 int tmp=-2e9; 33 ans++; 34 while(j<=n&&a[j].fi<=now) 35 { 36 tmp=max(tmp,a[j].sc); 37 j++; 38 } 39 if(tmp<=now) 40 { 41 ans=-1; 42 break; 43 } 44 now=tmp; 45 if(now>=t) break; 46 i=j-1; 47 } 48 if(now<t) ans=-1; 49 cout<<ans<<'\n'; 50 51 52 53 }
5. 所有数 到中位数的距离之和 最小
题目链接:https://www.acwing.com/problem/content/106/
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 const double eps=1e-9; 6 #define ll long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 int a[maxn]; 12 13 14 15 16 int main() 17 { 18 ios::sync_with_stdio(0); 19 cin.tie(0); 20 int n; 21 cin>>n; 22 for(int i=1;i<=n;i++) cin>>a[i]; 23 sort(a+1,a+1+n); 24 ll ans=0; 25 int x=a[(n+1)/2]; 26 for(int i=1;i<=n;i++) ans+=abs(x-a[i]); 27 cout<<ans<<'\n'; 28 29 30 31 }
6 耍杂技的牛 特别一点的贪心,根据两个值的排序来贪心 类似题是国王游戏
题目链接:https://www.acwing.com/problem/content/127/
考虑 1 2 放 和2 1 这样放 我们想让 1 2 更小 w2-s1<w1-s2 整理得 s1+w2>s2+w2 于是猜测按照这样排序即可
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 const int mod=1e9+7; 5 const double eps=1e-9; 6 #define ll long long 7 #define pi pair<int,int> 8 #define fi first 9 #define sc second 10 #define pb push_back 11 12 struct ac 13 { 14 int w,s; 15 bool operator<(ac a) 16 { 17 return w+s>a.w+a.s; 18 } 19 }; 20 ac a[maxn]; 21 22 23 int main() 24 { 25 ios::sync_with_stdio(0); 26 cin.tie(0); 27 int n; 28 cin>>n; 29 for(int i=1;i<=n;i++) cin>>a[i].w>>a[i].s; 30 sort(a+1,a+1+n); 31 ll ans=-1e18; 32 ll sum=0; 33 for(int i=n;i>=1;i--) 34 { 35 ans=max(ans,sum-a[i].s); 36 sum+=a[i].w; 37 } 38 cout<<ans<<'\n'; 39 40 41 42 }
7.题目链接:https://www.acwing.com/problem/content/description/112/
思路:左端点降序排序 每次选最大的能满足的 或者 右端点升序排序 每次选能满足的最小的防晒霜
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=3e3+10; 10 const int mod=1e9+7; 11 12 13 struct ac 14 { 15 int l,r; 16 bool operator<(ac a) 17 { 18 return r<a.r; 19 } 20 }; 21 ac a[maxn]; 22 pi b[maxn]; 23 24 25 int main() 26 { 27 ios::sync_with_stdio(0); 28 cin.tie(0); 29 int n,m; 30 cin>>n>>m; 31 for(int i=1;i<=n;i++) 32 { 33 int l,r; 34 cin>>l>>r; 35 a[i]={l,r}; 36 } 37 for(int i=1;i<=m;i++) 38 { 39 cin>>b[i].fi>>b[i].sc; 40 } 41 sort(a+1,a+1+n); 42 sort(b+1,b+1+m); 43 int ans=0; 44 for(int i=1;i<=n;i++) 45 { 46 for(int j=1;j<=m;j++) 47 { 48 int x=b[j].fi; 49 if(b[j].sc&&x<=a[i].r&&x>=a[i].l) 50 { 51 ans++; 52 b[j].sc--; 53 break; 54 } 55 } 56 } 57 cout<<ans<<'\n'; 58 59 60 61 62 63 }
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=3e3+10; 10 const int mod=5000011; 11 12 13 struct ac 14 { 15 int l,r; 16 bool operator<(ac a) 17 { 18 return l>a.l; 19 } 20 }; 21 ac a[maxn]; 22 pi b[maxn]; 23 24 25 int main() 26 { 27 ios::sync_with_stdio(0); 28 cin.tie(0); 29 int n,m; 30 cin>>n>>m; 31 for(int i=1;i<=n;i++) 32 { 33 int l,r; 34 cin>>l>>r; 35 a[i]={l,r}; 36 } 37 sort(a+1,a+1+n); 38 for(int i=1;i<=m;i++) 39 { 40 cin>>b[i].fi>>b[i].sc; 41 } 42 sort(b+1,b+1+m); 43 reverse(b+1,b+1+m); 44 int ans=0; 45 for(int i=1;i<=n;i++) 46 { 47 for(int j=1;j<=m;j++) 48 { 49 int x=b[j].fi; 50 if(x>=a[i].l&&x<=a[i].r&&b[j].sc) 51 { 52 b[j].sc--; 53 ans++; 54 break; 55 } 56 } 57 } 58 cout<<ans<<'\n'; 59 60 61 62 63 }
8.

浙公网安备 33010602011771号