好像接觸過不少區間覆蓋類的問題了,寫個部落格小結一下。
1,求最大覆蓋次數
問題描述:相當於給你一些區間,每次給這些區間內的點值都加一(初始都為0),然後問最大的值是多少。(也就是單點的最大覆蓋次數)
解決思路:顯然樹狀陣列可以很好地解決,複雜度nlogn,顯得有些大材小用了。現在有乙個好寫複雜度還低一點的辦法:把所有區間的左端點標為1,右端點標為-1,再從頭到尾遍歷一遍加上當前點的值,維護ans為最大值即可。
tips:為了防止乙個區間的右端點和另乙個的左端點重合導致答案錯誤,採取r++操作,可以證明不會影響結果。
**實現:
#include#include#include#include#include#include#include#include#include#include#include#include#include#define fast ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
int a[maxn];
int main()
int t = 0, ans = -inf;
for(int i = 1; i <= n; i++)
cout << ans << endl;
return 0;
}
2,求最多不相交區間
問題描述:經典例題:乙個人要參加一些會議,給你這些會議的開始和結束時間,問你他最多能參加多少會議。
解題思路:貪心的思想做。貪心策略:哪個越早結束就先參加哪個。結構體排序,按結束時間排,再貪心遍歷求解即可。
**實現:
#include#include#include#include#include#include#include#include#include#include#include#include#include#define fast ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e5 + 5;
using namespace std;
struct hia;
bool cmp(hia x, hia y)
hia z[maxn];
int main()
printf("%d\n", sum);
return 0;
}
例題:略略略
3,求被覆蓋i次的點的個數
問題描述:給你n個區間,分別求出被覆蓋1-n次的點的個數
解題思路:把端點從小到大排個序,左端點標個1,右端點標個-1(實際上是右端點的後面一位,避免左端點和另乙個的右端點重合情況的干擾),從左到右掃一遍,這樣就能很方便地求出不同區間覆蓋次數的值。
如圖,給兩個區間[1,7], [5, 12],用now記錄當前我們加的字首和,我們在遍歷到5的時候,有cnt[1] += (5-3),(now ==1)遍歷到8的時候,cnt[2] += (8 - 5),(now == 2)(其實這裡是區間[5,7]的貢獻,這也能解釋為什麼在標記的時候標記右端點的後一位),再遍歷到13,cnt[1] += (13 - 8),(now == 1)。這樣就能很好的完成記錄。
**:(用map顯然更方便一點)
#include#include#include#include#include#include#include#include#include#include#include#include#include#define fast ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)2e5 + 5;
using namespace std;
mapm;
ll cnt[maxn];
int main()
int now = 0;
ll t = 0;
map::iterator it;
for(it = m.begin(); it != m.end(); it++)
for(int i = 1; i < n; i++)
printf("%lld ", cnt[i]);
printf("%lld\n", cnt[n]);
return 0;
}
例題:cross fire!!!
4,求最少的能覆蓋區間的區間數
大意:給乙個區間[l, r],再給一些[l[i], r[i]],求用這些區間覆蓋[l, r]的最少數目
解決思路:貪心解決。把這些區間以左端點進行排序,先選擇第乙個區間,之後的貪心策略就是選擇在可選範圍內的,選擇右端點最大的區間。
**:
#include#include#include#include#include#include#include#include#include#include#include#include#include#define fast ios::sync_with_stdio(false)
#define lowbit(x) x&(-x)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = 25005;
using namespace std;
struct hia a[maxn];
bool cmp(hia x, hia y)
int main()
sort(a, a + n, cmp);
int ans = 0, i = 0, temp = 0;
while(temp < t && i < n)
temp = top;
} if(temp < t) puts("-1");
else printf("%d\n", ans);
return 0;
}
(此**可 ac poj2376)
5,求一段區間覆蓋了多少個其他的區間
大意:給你一些區間,有一些詢問,每次詢問給乙個區間,輸出這個區間覆蓋了多少區間
解題思路:用二維字首和來做。乙個區間用a[l, r]來表示。詢問的時候就相當於求[l, l] 到 [r, r]這個矩形中的元素數目
即sum[r][r] - sum[r][l-1] - sum[l-1][r] + sum[l-1][l-1]
#include#include#include#include#include#include#include#include#include#include#include#include#include#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define pii pair#define all(x) x.begin(), x.end()
#define fast ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int mod = (int)1e9 + 7;
const int maxn = (int)150000 + 5;
using namespace std;
int sum[505][505];
int main()
for(int i = 1; i <= n; i++)
} while(q--)
return 0;
}
例題:d - atcoder express 區間貪心問題小結(區間選點,區間覆蓋,區間選取)
貪心演算法 思想 什麼是貪心演算法,什麼算得上是貪心 貪心演算法 又稱貪婪演算法 是指,在對問題求解時,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,只做出在某種意義上的區域性最優解。貪心演算法不是對所有問題都能得到整體最優解,關鍵是貪心策略的選擇,選擇的貪心策略必須具備無後效性...
區間覆蓋問題
time limit 1000ms memory limit 65536k 用i來表示x座標軸上座標為 i 1,i 的長度為1的區間,並給出n 1 m 200 個不同的整數,表示n個這樣的區間。現在要求畫m條線段覆蓋住所有的區間,條件是 每條線段可以任意長,但是要求所畫線段的長度之和最小,並且線段的...
區間覆蓋問題
time limit 1000ms memory limit 65536k 用i來表示x座標軸上座標為 i 1,i 的長度為1的區間,並給出n 1 m 200 個不同的整數,表示n個這樣的區間。現在要求畫m條線段覆蓋住所有的區間,條件是 每條線段可以任意長,但是要求所畫線段的長度之和最小,並且線段的...