題意:每個線段有左端點,右端點和積分,找出互不覆蓋的線段的積分和的最大值。
和線段覆蓋2唯一的區別就在於資料範圍變大了,至於它的空間限制縮小對用dp做這個題並沒有什麼影響。
先說下線段覆蓋2的做法:按左右端點排序都可以(線段覆蓋4需要按右端點排序,這裡按右端點從小到大排序來講),第一層迴圈從左到右列舉每個點,第二層迴圈去列舉右端點比它小的點,找出右端點小於等於它的左端點且dp值最大的點,用它來求出這個點的dp值。這是o(n²)的做法,n在10³左右可以採用。
資料範圍增大至10的6次方,那麼我們就只能用o(nlogn)及以下的演算法,也就是說我們要優化第二層迴圈,使其能夠更快得求出dp值,這裡我用了兩個優化。
線段覆蓋4之所以要按右端點排序是因為這樣我們更容易鎖定目標點(即右端點小於等於所求點的左端點且dp值最大的點)的大致位置,我們只需要找到右端點小於等於所求點左端點的點裡右端點最大的點,目標點就一定在這個點的左邊,然後我們再求一下1到這個點的最大dp值就可以求出所求點的dp值了。
上文所說的兩個優化:
1、二分求出右端點小於等於所求點左端點的點裡右端點最大的點。
2、記錄字首dp值的最大值。
這兩個優化都不難,這裡就不詳述了。細節看**。
#include
#include
#include
using
namespace
std;
const
long
long maxn=1000010;
struct re
re[maxn];
long
long f[maxn]=,mx[maxn]=;
long
long cmp(const re &a,const re &b)
return r;
}int main()
printf("%lld",ans);
return
0;}
Codevs 3012 線段覆蓋 4
3012 線段覆蓋 4 時間限制 1 s 空間限制 64000 kb 題目等級 gold 題目描述 description 數軸上有n條線段,線段的兩端都是整數座標,座標範圍在0 1000000,每條線段有乙個價值,請從n條線段中挑出若干條線段,使得這些線段兩兩不覆蓋 端點可以重合 且線段價值之和最...
codevs3012 線段覆蓋4
這個題很好想到它的無後效性,但是我並不是很會寫轉移方程,看了別人的題解以後豁然開朗,序列dp多是以序列的第幾位作為狀態來進行轉移的 include include include using namespace std intn long long ans 1000010 ans i 表示i以前所有...
CodeVS3012 線段覆蓋4(DP 二分)
這裡放傳送門 這道題如果是o n2 的dp是比較好想的,用f i 表示選了前i條線段並且第i條必選的最大價值,每次列舉乙個線段i的時候列舉它前面不和它重疊的線段j,用f j val i 更新。但是資料範圍這麼大就要考慮優化了。優化這種dp的話比較好想的思路就是省掉內層迴圈。內層迴圈幹的事情有兩個,乙...