贪心 总结 ###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 }
View Code
 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 }
View Code

 或者 左端点降序排序 一直选左端点即可

 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 }
View Code

 

 

 

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 }
View Code

 或者左端点降序排序

 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 }
View Code

 

 

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 }
View Code
 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 }
View Code

 

 

 

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 }
View Code

 

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code
 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 }
View Code

 

8.

 

posted @ 2021-02-15 22:02  canwinfor  阅读(9)  评论(0)    收藏  举报