CODEVS 3037 線段覆蓋 5

2021-06-28 18:46:45 字數 1901 閱讀 2663

描述

數軸上有n條線段,線段的兩端都是整數座標,座標範圍在0~10^18,每條線段有乙個價值,請從n條線段中挑出若干條線段,使得這些線段兩兩不覆蓋(端點可以重合)且線段價值之和最大。

分析

提供兩種思路:

利用離散化. 因為這道題本來就是離散化的例題. 將點排序後依次賦值(1~2n, n為線段的條數), 再通過結構體裡的資訊將離散化後的點的座標對映到線段上.

利用二分法直接dp. 看到題解裡有二分兩個字, 自己yy出一套二分的做法不過好像和題解裡的不一樣: 將線段按終點從小到大排序, 考慮線段i, 用 f[i][0] 記錄不選 i 的最大權值和, f[i][1] 記錄選擇 i 的最大權值和. 那麼顯然有 f[i][0] = max. 然後二分 (upper_bound()) 查詢最後乙個可以接在 i 前的線段 j, 那麼 f[i][1] = max + v[i].

不過尷尬的是第二種方法wa了四個點…而且差了不是乙個數量級…

**

3791ms, 65mb

// 1. 離散化

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1000000 + 10;

ll f[maxn<<1];

struct line

}lines[maxn];

struct point

}points[maxn<<1];

int main() ;

points[(i<<1)^1] = (point) ;

}sort(points, points + 2*n);

// discretization

int base = 0, cnt = 0;

while(base < 2*n)

for(int i = 0; i < 2*n; i++)

sort(lines, lines + n);

ll ans = 0ll;

for(int cur = 0, pre = 0; cur < n; cur++)

ans = max(ans, (f[l.t] = max(f[l.t], f[l.s] + l.v)));

}printf("%lld\n", ans);

return

0;}

// 二分

#include

#include

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1000000 + 10;

ll f[maxn][2], t[maxn];

struct line

}lines[maxn];

int main() ;

}sort(lines, lines + n);

for(int i = 0; i < n; i++) t[i] = lines[i].t; // 用於二分查詢

f[0][0] = 0; f[0][1] = lines[0].v;

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

printf("%d\n", max(f[n-1][0], f[n-1][1]));

return

0;}

codevs3037 線段覆蓋5 離散化DP

codevs3037 線段覆蓋5 不懂某些人為什麼要用bit 這樣會帶壞小朋友的啊喂 雖然說刷到大師了寫個bit就是一分鐘的事 不過你強行加個log會很慢的阿喂,何況這題的log大概是20。其實我寫的也不好 並沒有1a而且錯誤還比較多 dp i 表示到離散化之後的端點i之前最大價值。然後把線段按右端...

Codevs 線段覆蓋1 2 3 4 5

對於線段覆蓋1 3,貪心,每次選取末端點靠前的,o n 掃一遍即可 話說這個題似乎排序最佔時間 當然dp也可以 include include define maxn 1000000 5 using namespace std struct line l maxn int main sort l 1...

codevs線段覆蓋 動態規劃

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