• 洛谷 P2487 [SDOI2011]拦截导弹


    题目描述

    某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

    在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。

    我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。

    输入输出格式

    输入格式:

    输出格式:

    输入输出样例

    输入样例#1:
    4
    3 30
    4 40
    6 60
    3 30
    
    输出样例#1:
    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
    ",double(clock())/1000.0)
    #define TO(j) printf(#j": %d
    ",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
    ", ans.v);
        rep0(i, n) printf("%.5lf ", prop[i]);
        putchar('
    ');
    }
    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;
        }
    }
  • 相关阅读:
    PHPCMS V9后台表单向导用户提交的信息新增“修改”的功能
    phpcms V9最实用的23个调用代码
    phpcms V9推荐位无法调用自定义字段的解决方法
    将博客搬至CSDN
    爬取淘宝商品信息selenium+pyquery+mongodb
    selenium库
    requests库+ajax数据分析+多线程爬取头条图集
    requests微博爬取Ajax数据+mongoDB存储
    redis存储
    pymongo操作MongoDB
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6916104.html
Copyright © 2020-2023  润新知