1. 程式人生 > >Bzoj2244: [SDOI2011]攔截導彈

Bzoj2244: [SDOI2011]攔截導彈

時間 span spa HA bzoj pre geo log class

題面

傳送門

Sol

每個導彈有時間,高度,速度
求時間遞增,高度,速度不降的最長的序列
然後還要求最長序列的方案以及每個導彈在最長序列中的方案

這個就是偏序問題辣,正反兩遍求出每個導彈為結尾開頭的序列最長長度
判斷是否在最長序列就二者相加判斷
然後記錄下方案,用\(double\)\(long\ long\)會炸

然後我選擇\(CDQ\)

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace
std; const int _(5e4 + 5); typedef long long ll; IL int Input(){ RG int x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1
) + (x << 3) + (c ^ 48); return x * z; } int n, g[2][_], c1[_], o1[_], len1, o2[_], len2; double f[2][_], c2[_]; struct Missile{ int id, h, v; IL void Reverse(){ id = n - id + 1, h = len1 - h + 1, v = len2 - v + 1; } IL int operator <(RG Missile B) const{ return
h != B.h ? h < B.h : id < B.id; } } q[_], p[_]; IL void Cls(RG int x){ for(; x <= len2; x += x & -x) c1[x] = c2[x] = 0; } IL void Add(RG int x, RG int l, RG double p){ for(; x <= len2; x += x & -x) if(l > c1[x]) c1[x] = l, c2[x] = p; else if(l == c1[x]) c2[x] += p; } IL void Query(RG int x, RG int &l, RG double &p){ for(; x; x -= x & -x) if(c1[x] > l) l = c1[x], p = c2[x]; else if(c1[x] == l) p += c2[x]; } IL void CDQ(RG int l, RG int r, RG int op){ if(l == r) return; RG int mid = (l + r) >> 1; for(RG int i = l, be = l, en = mid + 1; i <= r; ++i) if(q[i].id <= mid) p[be++] = q[i]; else p[en++] = q[i]; for(RG int i = l; i <= r; ++i) q[i] = p[i]; CDQ(l, mid, op); for(RG int i = mid + 1, j = l; i <= r; ++i){ while(j <= mid && q[j].h <= q[i].h) Add(q[j].v, g[op][q[j].id] + 1, f[op][q[j].id]), ++j; Query(q[i].v, g[op][q[i].id], f[op][q[i].id]); } for(RG int i = l; i <= mid; ++i) Cls(q[i].v); CDQ(mid + 1, r, op); for(RG int i = l, be = l, en = mid + 1; i <= r; ++i) if(en > r || (be <= mid && q[be].h <= q[en].h)) p[i] = q[be++]; else p[i] = q[en++]; for(RG int i = l; i <= r; ++i) q[i] = p[i]; } int main(RG int argc, RG char* argv[]){ n = Input(); for(RG int i = 1; i <= n; ++i){ q[i] = (Missile){i, Input(), Input()}; o1[++len1] = q[i].h, o2[++len2] = q[i].v; } sort(o1 + 1, o1 + len1 + 1), sort(o2 + 1, o2 + len2 + 1); len1 = unique(o1 + 1, o1 + len1 + 1) - o1 - 1; len2 = unique(o2 + 1, o2 + len2 + 1) - o2 - 1; for(RG int i = 1; i <= n; ++i){ q[i].h = lower_bound(o1 + 1, o1 + len1 + 1, q[i].h) - o1; q[i].v = lower_bound(o2 + 1, o2 + len2 + 1, q[i].v) - o2; q[i].h = len1 - q[i].h + 1, q[i].v = len2 - q[i].v + 1; g[0][i] = g[1][i] = 1, f[0][i] = f[1][i] = 1; } sort(q + 1, q + n + 1), CDQ(1, n, 0); for(RG int i = 1; i <= n; ++i) q[i].Reverse(); sort(q + 1, q + n + 1), CDQ(1, n, 1); reverse(g[1] + 1, g[1] + n + 1), reverse(f[1] + 1, f[1] + n + 1); RG int mx = 0; RG double sum = 0; for(RG int i = 1; i <= n; ++i) mx = max(mx, g[0][i]); printf("%d\n", mx); for(RG int i = 1; i <= n; ++i) if(g[0][i] == mx) sum += f[0][i]; for(RG int i = 1; i <= n; ++i){ if(g[0][i] + g[1][i] - 1 != mx) puts("0"); else printf("%.5lf\n", f[0][i] * f[1][i] / sum); } return 0; }

Bzoj2244: [SDOI2011]攔截導彈