首页 > 代码库 > 洛谷 P2487 [SDOI2011]拦截导弹
洛谷 P2487 [SDOI2011]拦截导弹
题目描述
某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。
输入输出格式
输入格式:
输出格式:
输入输出样例
4 3 30 4 40 6 60 3 30
2 0.33333 0.33333 0.33333 1.00000
说明
题目大意:求二维LDS,以及每个位置在LDS中出现的概率
破题
第14个点大概是有问题
头一次见到用double的计数题
h和v太大了,显然要先离散化
先考虑第一个问题,这是一个三维偏序关系,显然可以cdq分治解决,注意分治的顺序是左中右不是左右中
然后是第二个问题,考虑在cdq分治的时候同时记录一下LDS的个数,那么一个位置出现的概率就是(经过这个位置的LDS数量/总的LDS数量)
怎么求经过一个位置的LDS数量呢,我们考虑倒过来再做一遍二维LIS,显然如果一个位置在某个LDS中,那么 以它结尾的LDS长度+倒过来以它结尾的LIS长度=整个序列的LDS长度+1,而经过这个位置的LDS数量则是 以他结尾的LDS数量*倒过来以他结尾的LIS数量
然而这个东西longlong都存不下,必须开double
#include <iostream> #include <cstdlib> #include <cstdio> #include <algorithm> #include <string> #include <cstring> #include <cmath> #include <map> #include <stack> #include <set> #include <vector> #include <queue> #include <time.h> #define eps 1e-7 #define INF 0x3f3f3f3f #define MOD 1000000007 #define rep0(j,n) for(int j=0;j<n;++j) #define rep1(j,n) for(int j=1;j<=n;++j) #define pb push_back #define mp make_pair #define set0(n) memset(n,0,sizeof(n)) #define ll long long #define ull unsigned long long #define iter(i,v) for(edge *i=head[v];i;i=i->nxt) #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define print_runtime printf("Running time:%.3lfs\n",double(clock())/1000.0) #define TO(j) printf(#j": %d\n",j); //#define OJ using namespace std; const int MAXINT = 50010; const int MAXNODE = 100010; const int MAXEDGE = 2 * MAXNODE; char BUF, *buf; int read() { char c = getchar(); int f = 1, x = 0; while (!isdigit(c)) { if (c == ‘-‘) f = -1; c = getchar(); } while (isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar(); } return f * x; } char get_ch() { char c = getchar(); while (!isalpha(c)) c = getchar(); return c; } //------------------- Head Files ----------------------// int n, b[MAXINT], cnt_b, c[MAXINT], cnt_c; double prop[MAXINT]; struct res { int v; double cnt; res(int _v, double _c) : v(_v), cnt(_c) {} res() {} }; res add(res a, res b) { if (a.v == b.v) return res(a.v, a.cnt + b.cnt); if (a.v > b.v) return a; else return b; } struct missile { int h, v, id; res ans; } a[MAXINT], s[MAXINT]; struct node { int lb, rb; res ans; int tag; node *l, *r; void pushup() { ans = add(l->ans, r->ans); } void clear() { ans = res(-1, -1); tag = 0; } void pushdown() { if (tag != -1) { l->clear(); r->clear(); tag = -1; } } }; struct SegTree { node mp[MAXINT * 4]; node *root; int cnt; node *newnode(int l, int r) { node *p = &mp[cnt++]; p->lb = l; p->rb = r; return p; } void buildtree(int l, int r, node *&p) { p = newnode(l, r); if (r - l > 1) { buildtree(l, (l + r) / 2, p->l); buildtree((l + r) / 2, r, p->r); } } void clear() { root->clear(); } void insert(int pos, res v) { insert(pos, v, root); } void insert(int pos, res v, node *p) { if (p->rb - p->lb == 1) { p->ans = add(p->ans, v); return; } p->pushdown(); int mid = (p->lb + p->rb) / 2; if (pos < mid) insert(pos, v, p->l); else insert(pos, v, p->r); p->pushup(); } res query(int l) { res ret = query(l, INF, root); ret.v++; return ret; } res query2(int r) { res ret = query(0, r + 1, root); ret.v++; return ret; } res query(int l, int r, node *p) { if (r <= p->lb || l >= p->rb) return res(-1, -1); if (r >= p->rb && l <= p->lb) return p->ans; p->pushdown(); return add(query(l, r, p->l), query(l, r, p->r)); } } st; bool cmph(const missile & a, const missile & b) { return a.h > b.h; } bool cmph2(const missile & a, const missile & b) { return a.h < b.h; } bool cmpid(const missile & a, const missile & b) { return a.id < b.id; } bool cmpid2(const missile & a, const missile & b) { return a.id > b.id; } void cdq(int l, int r) { int mid = (l + r) / 2; if (r - l == 1) return; sort(a + l, a + r, cmpid); cdq(l, mid); sort(a + l, a + mid, cmph); sort(a + mid, a + r, cmph); int mx = 0, cnt = 0, i = l, j = mid; st.clear(); for (; i < mid; i++) { for (; j < r && a[j].h > a[i].h; j++) { a[j].ans = add(a[j].ans, st.query(a[j].v)); } st.insert(a[i].v, a[i].ans); } for (; j < r; j++) { a[j].ans = add(a[j].ans, st.query(a[j].v)); } cdq(mid, r); } void cdq2(int l, int r) { int mid = (l + r) / 2; if (r - l == 1) return; sort(s + l, s + r, cmpid2); cdq2(l, mid); sort(s + l, s + mid, cmph2); sort(s + mid, s + r, cmph2); int mx = 0, cnt = 0, i = l, j = mid; st.clear(); for (; i < mid; i++) { for (; j < r && s[j].h < s[i].h; j++) { s[j].ans = add(s[j].ans, st.query2(s[j].v)); } st.insert(s[i].v, s[i].ans); } for (; j < r; j++) { s[j].ans = add(s[j].ans, st.query2(s[j].v)); } cdq2(mid, r); } void get_input(); void work(); int main() { get_input(); work(); return 0; } void work() { st.buildtree(0, n, st.root); rep0(i, n) s[i] = a[i]; sort(s, s + n, cmpid2); cdq(0, n); cdq2(0, n); res ans(0, 0); rep0(i, n) { ans = add(ans, a[i].ans); } sort(a, a + n, cmpid); sort(s, s + n, cmpid); rep0(i, n) { if (s[i].ans.v + a[i].ans.v != ans.v + 1) prop[i] = 0; else { prop[i] = s[i].ans.cnt*a[i].ans.cnt / double(ans.cnt); } } printf("%lld\n", ans.v); rep0(i, n) printf("%.5lf ", prop[i]); putchar(‘\n‘); } void get_input() { n = read(); rep0(i, n) { a[i].id = i; a[i].h = read(); a[i].v = read(); a[i].ans = res(1, 1); b[cnt_b++] = a[i].h; c[cnt_c++] = a[i].v; } sort(b, b + cnt_b); sort(c, c + cnt_c); cnt_b = unique(b, b + cnt_b) - b; cnt_c = unique(c, c + cnt_c) - c; rep0(i, n) { a[i].h = lower_bound(b, b + cnt_b, a[i].h) - b; a[i].v = lower_bound(c, c + cnt_c, a[i].v) - c; } }
洛谷 P2487 [SDOI2011]拦截导弹