题面
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;
}