描述數軸上有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...