線段覆蓋一類的貪心
阿新 • • 發佈:2020-11-23
統一思路:對右端點進行排序,嘗試維護最優子結構(取最差的)
區間完全覆蓋問題
給定一個長度為m的區間,再給出n條線段的起點和終點(注意這裡是閉區間)
求最少使用多少條線段可以將整個區間完全覆蓋
- 對右端點進行從大到小排序,每次選最小的左端點進行更新
最大不相交覆蓋
給定一個長度為m的區間和n條線段的起點和終點,
從中選取儘量多的線段,使得線段都是互不相交的
- 對右端點進行從小到大排序,每次操作保證線段條數最多且右端點最小
- 按右端點排序後,可以考慮DP
區間選點問題
給定一個長度為m的區間,n條線段和這n條線段上至少有多少點
整個區間內最少選擇幾個點,使其滿足每一條線段的要求.
- 按右端點從小到大排序,如果右端點相同按左端點排序,依次加點
- 可以對字首和陣列進行差分後差分約束系統
Luogu P2887 [USACO07NOV]Sunscreen G
有C個奶牛去晒太陽 (1 <=C <= 2500),每個奶牛各自能夠忍受的陽光強度有一個最小值和一個最大值。
奶牛就得塗抹防晒霜,防晒霜的作用是讓陽光照在身上的陽光強度固定為某個值。
給出了L種防晒霜。每種的數量和固定的陽光強度也給出來了
每個奶牛隻能抹一瓶防晒霜,最後問能夠享受晒太陽的奶牛有幾個。
- 抽象模型:存在若干線段和若干點,每條線段只能覆蓋一個點,問最多能覆蓋多少點
按右端點從小到大排序,每次選距離左端點最近的點(即最差情況)
#include<bits/stdc++.h> using namespace std; const int N=3005; int n,m,b[N],ans; struct A{int a,b; }a[N]; bool cmp(A i,A j) { return i.b<j.b; } set<int>s; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].a,&a[i].b); } sort(a+1,a+n+1,cmp); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); b[x]+=y; } for(int i=1;i<=1000;i++){ if(b[i]) s.insert(i); } for(int i=1;i<=n;i++) { auto t=s.lower_bound(a[i].a); if(t!=s.end()&&*t<=a[i].b) { b[*t]--; if(b[*t]==0) s.erase(t); ans++; } } printf("%d\n",ans); return 0; }