线段覆盖的三个题目
我们可以先对线段进行排序,可能出现如下三种情况
1不想交
2相交,不包含
3相交,包含
http://tzcoder.cn/acmhome/problemdetail.do?&method=showdetail&id=1532
http://tzcoder.cn/acmhome/problemdetail.do?method=showdetail&id=5625
https://www.luogu.com.cn/problem/P1204
#include<bits/stdc++.h> using namespace std; struct node { int L,R; }a[5005]; bool cmp(node a,node b) { //因为后来相等的关系我其实没有用到 //不排序也行,我只需要当前的L和R,只要起点最优就可以 return a.L<b.L; } int main() { int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i].L>>a[i].R; sort(a,a+n,cmp); //排序之后满足起点最优 //用L表示当前最远的L,用R表示当前最远的R int L=a[0].L,R=a[0].R; int ans1=0,ans2=0; for(int i=1;i<n;i++) { //这个不满足,对应第二三种,我需要更新我的R if(a[i].L<=R) { //直接取最大R R=max(R,a[i].R); } else { //以下为不相交,也就是第一种情况 //至少有一人在挤奶,就是上一次我们统计的那一段 ans1=max(ans1,R-L); //无人挤奶的时间段就是当前的L和上一次的R ans2=max(ans2,a[i].L-R); //更新L和R L=a[i].L; R=a[i].R; } } //最后一次有可能是相交了,所以还要更新一次 ans1=max(ans1,R-L); cout<<ans1<<" "<<ans2<<"\n"; return 0; }
第四个题目需要贪心
我们可以按照右端点进行排序
#include <bits/stdc++.h> using namespace std; struct T { int l, r, w; } a[5005]; int cmp(T A, T B) { return A.r < B.r; } int ans, vis[30005]; int main() { int n,h; cin>>n>>h; for (int i = 0; i < h; i++) cin>>a[i].l>>a[i].r>>a[i].w; //按照右端点进行排序 sort(a, a + h, cmp); for (int i = 0; i < h; i++) { int s = 0; //看看左边已经有多少个被填了,解决情况3 for (int j = a[i].l; j <= a[i].r && s < a[i].w; j++) if (vis[j])s++; //从右向左填,解决剩下的 //基本思想,少种树,那么就尽力让重合的种上,解决2,3即可 for (int j = a[i].r; j >= a[i].l && s < a[i].w; j--) { if (!vis[j]) { s++,ans++,vis[j] = 1; } } } cout<<ans<<"\n"; return 0; }
直接维护速度并不快,解决区间问题,我们可以使用线段树,但是这个情况2线段树也不行了,所以可以合并一下线段
本文来自博客园,作者:暴力都不会的蒟蒻,转载请注明原文链接:https://www.cnblogs.com/BobHuang/p/12273406.html