Codevs 線段覆蓋1 2 3 4 5

2021-07-24 08:52:24 字數 1726 閱讀 9331

對於線段覆蓋1、3,貪心,每次選取末端點靠前的,o(n)掃一遍即可(話說這個題似乎排序最佔時間)。(當然dp也可以)#include#include#define maxn 1000000+5

using namespace std;

struct line

}l[maxn];

int main()

sort(l+1,l+n+1);

int pos=-1,cnt=0;i=1;

while(i<=n)

i++;

} cout《但是對於線段有權值的情況,可以證明貪心是行不通的,這時候就必須dp

我的做法是:設dp[i]表示到第i條線段可獲得的最大價值,容易得到這樣的狀態轉移方程:

dp[i]=max(dp[i-1],dp[j]+line[i].c),j表示距離i最近的與i沒有交集的線段。

對於查詢線段j,樸素的做法就是從i開始向前列舉,然而這樣只能通過線段覆蓋2,對於4會tle兩個點,5會tle7個點。

仔細分析線段性質,可以發現由於我們對線段進行了排序,所以線段的末端點對於線段的編號是具有單調性的,所以可以使用二分查詢第乙個滿足此性質的線段。

#include#include#define int long long

#define maxn 1000000+5

using namespace std;

struct line

else if(l[mid].e<=l[i].b)

} if(l[lf].e<=l[i].b)return lf;

return lf-1;

} else

}#undef int

int main()

sort(l+1,l+n+1);

l[0].b=l[0].e=l[0].c=-1;

for(int i=1;i<=n;i++)

dp[i]=max(dp[i-1],dp[bsearch(i,0)]+l[i].c);

cout《然而還有另一種dp思路,(%zy),設dp[i]表示在座標i的最大價值,可行的一種狀態轉移方程為:

f[line[i].e]=max(f[line[i].e],f[line[i].b]+line[i].c);

轉移時列舉line[i].e而不是每個座標

在每次迴圈時,拿f[line[i].e]來更新從f[iine[i].e+1]到f[iine[i+1].e]中的所有點,這樣可以實現在轉移時選或不選這條線段的操作。

對於線段覆蓋4、5,資料範圍過大,需要離散化。

#include#include#includeusing namespace std;

struct segment

a[1000005];

struct mes

t;long long n,i,j,pre,p,f[1000005];

struct cmp2

};priority_queue,cmp2> q;

bool cmp(segment x,segment y)

);//奇數節點為begin

q.push((mes));//偶數節點為end

} pre=q.top().pos;

for(i=1;i<=n+n;i++)

if((t.rank&1)==1) a[(t.rank+1)>>1].b=p;

else a[(t.rank)>>1].e=p;

} sort(a+1,a+n+1,cmp);

for(i=1;i

codevs線段覆蓋 動態規劃

題目描述 description 給定x軸上的n 0輸入描述 input description 輸入第一行是乙個整數n。接下來有n行,每行有二個空格隔開的整數,表示一條線段的二個端點的座標。輸出描述 output description 輸出第一行是乙個整數表示最多剩下的線段數。樣例輸入 samp...

codeVS 1214 線段覆蓋

題目描述 description 給定x軸上的n 0輸入描述 input description 輸入第一行是乙個整數n。接下來有n行,每行有二個空格隔開的整數,表示一條線段的二個端點的座標。輸出描述 output description 輸出第一行是乙個整數表示最多剩下的線段數。樣例輸入 samp...

codevs1214 線段覆蓋

題目描述 description 給定x軸上的n 0 輸入描述 input description 輸入第一行是乙個整數n。接下來有n行,每行有二個空格隔開的整數,表示一條線段的二個端點的座標。輸出描述 output description 輸出第一行是乙個整數表示最多剩下的線段數。樣例輸入 sam...