Solution SDOI2011 攔截飛彈

2022-09-21 01:03:08 字數 2624 閱讀 3296

link

看到第一問,不難想到是個有兩個屬性的 \(\text\) 問題,很容易想到 \(\text\)

\(n^2\)

\(\text\) 的暴力 dp 。

定義 \(\text\) 為以當前飛彈結尾的最多攔截數,\(\text\)

\(n^2\)

\(\text\) 轉移。

這個問題有三個要求 : \(id_i < id_j,h_i \ge h_j,v_i \ge v_j\) ,是個三維偏序問題,可以用 cdq 來優化 ta。

cdq 求解問題是將乙個區間分為左右兩個小區間,先求解兩個區間的子問題,再求跨區間的情況。

但對於 dp 轉移來說,若按照正常的順序,則在求解右邊的子區間時,右邊的每個 dp 的值並沒有得到。

所以在求完左區間的子問題後,要先將 dp 從左區間轉移到右區間,再求解右區間。

再看到第二問,求在攔截的飛彈最多的情況下攔截當前飛彈的概率,即是攔下當前飛彈的方案數除以總方案數。

直接求出攔下當前飛彈的方案數比較困難,不妨將其拆分成兩個子問題:以當前飛彈結尾的方案數、以當前飛彈開始的方案數。而總方案數就等於兩子問題方案數的乘積。

而方案數的轉移可以與第一問中的最多的攔截數一起轉移。兩種情況用兩個 cdq 處理就行了。

有些細節,調的挺久的。。。

#include #include #include using namespace std;

#define ll long long

#define rep(i, j, k) for(int i = (j); i <= (k); i ++)

#define per(i, j, k) for(int i = (j); i >= (k); i --)

const int maxn = 5e4;

int n;

int bit[maxn + 5], dp1[maxn + 5], dp2[maxn + 5];

double bitf[maxn + 5], fl[maxn + 5], fr[maxn + 5], f[maxn + 5];

namespace bit

} int get_max (int x)

double get_sum (int x, int dp)

return sum;

}void clear (int x)

void update2 (int x, int y, double f)

} int get_max2 (int x)

double get_sum2 (int x, int dp)

return sum;

}void clear2 (int x)

}using namespace bit;

struct node a[maxn + 5];

bool cmph1 (node x, node y)

bool cmph2 (node x, node y)

bool cmpv1 (node x, node y)

bool cmpv2 (node x, node y)

void merge (int l1, int r1, int l2, int r2)

int new = get_max (a[j].t) + 1; //這次的最優即為還滿足 t 的偏序條件的長度中的最大值 + 1

if (a[j].dpl < new) else if (a[j].dpl == new)

}rep (k, l1, i - 1) clear (a[k].t); //記得清空

sort (a + l2, a + 1 + r2, cmph1); //排回以 h 為關鍵字的順序

}void cdq (int l, int r)

void merge1 (int l1, int r1, int l2, int r2)

int new = get_max2 (a[j].t) + 1;

if (a[j].dpr < new) else if (a[j].dpr == new)

}rep (k, l1, i - 1) clear2 (a[k].t);

sort (a + l2, a + 1 + r2, cmph2);

}void cdq1 (int l, int r)

int main ()

sort (a + 1, a + 1 + n, cmph1);//事先按 h 排序,則在 cdq 中,大區間的左子區間中的每乙個都與右子區間中的滿足 h 的偏序關係

cdq (1, n);

rep (i, 1, n) dp1[a[i].t] = a[i].dpl, fl[a[i].t] = a[i].fl;

sort (a + 1, a + 1 + n, cmph2);

cdq1 (1, n);

rep (i, 1, n) dp2[a[i].t] = a[i].dpr, fr[a[i].t] = a[i].fr;

int ans = 0;

double tot = 0;

rep (i, 1, n)

rep (i, 1, n)

printf ("%d\n", ans);

rep (i, 1, n)

return 0;

}

物件導向部分 201

小夥伴們,還在為不知道怎麼下手而頭疼嗎,我們程式競賽協會來幫你們啦 啦啦啦。另外,如果有對程式設計含有濃厚興趣的同學,我們隨時歡迎你們的加入喲 策劃 譚兆飛 程式設計 管懷文 協助 一號人員要求給她打碼 乾脆二號也打碼好了o o 其實只是提供了題目啦 物件導向部分 201 include inclu...

2 01揹包問題

有 nn 件物品和乙個容量是 vv 的揹包。每件物品只能使用一次。第 ii 件物品的體積是 vivi,價值是 wiwi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。輸入格式 第一行兩個整數,n,vn,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 n...

2 01揹包問題

有 nn 件物品和乙個容量是 vv 的揹包。每件物品只能使用一次。第 ii 件物品的體積是 vivi,價值是 wiwi。求解將哪些物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。第一行兩個整數,n,vn,v,用空格隔開,分別表示物品數量和揹包容積。接下來有 nn 行,每...