zoukankan      html  css  js  c++  java
  • bzoj 2244: [SDOI2011]拦截导弹 cdq分治

    2244: [SDOI2011]拦截导弹

    Time Limit: 30 Sec  Memory Limit: 512 MBSec  Special Judge
    Submit: 237  Solved: 103
    [Submit][Status][Discuss]

    Description

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

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

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

    Input

    第一行包含一个正整数n,表示敌军导弹数量;

    下面行按顺序给出了敌军所有导弹信息:

    i+1行包含2个正整数hivi,分别表示第枚导弹的高度和速度。

    Output

    输出包含两行。

    第一行为一个正整数,表示最多能拦截掉的导弹数量;

    第二行包含n01之间的实数,第i个数字表示第i枚导弹被拦截掉的概率(你可以保留任意多位有效数字)。

    Sample Input

    4

    3 30

    4 40

    6 60

    3 30

    Sample Output

    2

    0.33333 0.33333 0.33333 1.00000

    【数据规模和约定】


    对于100%的数据,1≤n≤5*104, 1≤hi ,vi≤109;

    均匀分布着约30%的数据,所有vi均相等。

    均匀分布着约50%的数据,满足1≤hi ,vi≤1000。

    HINT

    鸣谢kac提供sj程序!

      这次算是把cdq分治给搞懂了。这道题的做法网上的题解说的已经比较详细了,这里就不重复了。

      值得注意的是,随机选择最优方案和沿着最优方案等概率向后走是两个完全不同的东西,后者还要复杂一些,要正扫反扫正扫三遍分治,然而我居然写的就是那个。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 100000
    #define MAXT MAXN*4
    #define lch (now<<1)
    #define rch (now<<1^1)
    #define smid ((l+r)>>1)
    #define INF 0x3f3f3f3f
    typedef double real;
    struct aaa
    {
            aaa(){}
            aaa(int x,int y,int id):x(x),y(y),id(id){}
            int x,y;
            int id;
    }al[MAXN];
    bool cmp_x(aaa a1,aaa a2)
    {
            return a1.x<a2.x;
    }
    bool cmp_y(aaa a1,aaa a2)
    {
            return a1.y<a2.y;
    }
    bool cmp_id(aaa a1,aaa a2)
    {
            return a1.id<a2.id;
    }
    struct bbb
    {
            int id;
            int opt;
            int x,y,pos;
            int d;
            //opt==1(Modify (x,y) [+/-])
            //opt==2(Query [x,y] into z[+/-]);
    }bl[MAXN],cl[MAXN];
    bool cmp_bbb_x(bbb b1,bbb b2)
    {
            if (b1.x==b2.x)return b1.opt<b2.opt;
            return b1.x<b2.x;
    }
    bool cmp_bbb_x2(bbb b1,bbb b2)
    {
            if (b1.x==b2.x)return b1.opt<b2.opt;
            return b1.x>b2.x;
    }
    bool cmp_bbb_id(bbb b1,bbb b2)
    {
            return b1.id<b2.id;
    }
    int totb=0;
    int totnxt[MAXN];
    int maxx,maxy;
    pair<int,real> dpv[MAXN],dpv2[MAXN];
    template<typename T> pair<int,T> deal(pair<int,T> p1,pair<int,T> p2)
    {
            if (p1.first==p2.first)
                    return make_pair(p1.first,p1.second+p2.second);
            else if (p1.first<p2.first)
                    return p2;
            else
                    return p1;
    }
    bool rev;
    pair<int,real> tarr[MAXN];
    void Add_tarr(int pos,pair<int,real> pr)
    {
            if (rev)pos=maxy+1-pos;
            while (pos<MAXN)
            {
                    tarr[pos]=deal(tarr[pos],pr);
                    pos+=pos&(-pos);
            }
    }
    void Clear_tarr(int pos)
    {
            if (rev)pos=maxy+1-pos;
            while (pos<MAXN)
            {
                    tarr[pos]=make_pair(0,0);
                    pos+=pos&(-pos);
            }
    }
    pair<int,real> Qry_tarr(int pos)
    {
            if (rev)pos=maxy+1-pos;
            pair<int,real> ret=make_pair(-INF,0);
            while (pos)
            {
                    ret=deal(ret,tarr[pos]);
                    pos-=pos&(-pos);
            }
            return ret;
    }
    void solve(int l,int r)
    {
            if (l==r)return ;
            int mid=(l+r)>>1;
            solve(l,mid);
            int totc=0;
            for (int i=l;i<=mid;i++)
                    if (bl[i].opt==1)
                            cl[totc++]=bl[i];
            for (int i=mid+1;i<=r;i++)
                    if (bl[i].opt==2)
                            cl[totc++]=bl[i];
            if (rev)
                    sort(cl,cl+totc,cmp_bbb_x2);
            else
                    sort(cl,cl+totc,cmp_bbb_x);
            for (int i=0;i<totc;i++)
            {
                    if (cl[i].opt==1)
                    {
                            Add_tarr(cl[i].y,dpv[cl[i].pos]);
                    }else if (cl[i].opt==2)
                    {
                            pair<int,real> res=Qry_tarr(cl[i].y);
                            res.first++;
                            dpv[cl[i].pos]=deal(dpv[cl[i].pos],res);
                    }
            }
            for (int i=0;i<totc;i++)
            {
                    if (cl[i].opt==1)
                    {
                            Clear_tarr(cl[i].y);
                    }
            }
            sort(bl+l,bl+r+1,cmp_bbb_id);
            solve(mid+1,r);
    }
    
    int main()
    {
            freopen("input.txt","r",stdin);
            int n,m,x,y,z;
            scanf("%d",&n);
            al[0]=aaa(INF/2,INF/2,0);
            for (int i=1;i<=n;i++)
            {
                    scanf("%d%d",&al[i].x,&al[i].y);
                    al[i].id=i;
            }
            n++;
            al[n]=aaa(-INF/2,-INF/2,n);n++;
            sort(al,al+n,cmp_x);
            x=-INF;y=0;
            for (int i=0;i<n;i++)
            {
                    if (al[i].x!=x)y++;
                    x=al[i].x;
                    al[i].x=y;
            }
            maxx=y;
            sort(al,al+n,cmp_y);
            x=-INF,y=0;
            for (int i=0;i<n;i++)
            {
                    if (al[i].y!=x)y++;
                    x=al[i].y;
                    al[i].y=y;
            }
            maxy=y;
            sort(al,al+n,cmp_id);
            //====================================
            totb=0;
            for (int i=n-1;i>=0;i--)
            {
                    bl[totb].opt=2;
                    bl[totb].x=al[i].x;
                    bl[totb].y=al[i].y;
                    bl[totb].pos=i;
                    bl[totb].d=1;
                    bl[totb].id=totb;
                    totb++;
                    bl[totb].opt=1;
                    bl[totb].x=al[i].x;
                    bl[totb].y=al[i].y;
                    bl[totb].pos=i;
                    bl[totb].id=totb;
                    totb++;
            }
            dpv[n-1]=make_pair(0,1);
            solve(0,totb-1);
            //for (int i=0;i<n;i++)printf("%d %.2lf
    ",dpv[i].first,dpv[i].second);
            memcpy(dpv2,dpv,sizeof(dpv));
            memset(dpv,0,sizeof(dpv2));
            totb=0;
            for (int i=0;i<n;i++)
            {
                    bl[totb].opt=2;
                    bl[totb].x=al[i].x;
                    bl[totb].y=al[i].y;
                    bl[totb].pos=i;
                    bl[totb].id=totb;
                    totb++;
                    bl[totb].opt=1;
                    bl[totb].x=al[i].x;
                    bl[totb].y=al[i].y;
                    bl[totb].pos=i;
                    bl[totb].id=totb;
                    totb++;
            }
            dpv[0]=make_pair(0,1);
            rev=true;
            solve(0,totb-1);
            //for (int i=0;i<n;i++)printf("%d %.2lf
    ",dpv[i].first,dpv[i].second);
            printf("%d
    ",dpv[n-1].first-1);
            for (int i=1;i<n-1;i++)
                    if (dpv[i].first+dpv2[i].first!=dpv[n-1].first)
                            printf("%.5lf ",0.0);
                    else
                            printf("%.5lf ",dpv[i].second*dpv2[i].second/dpv[n-1].second);
    }
  • 相关阅读:
    PHP ftp_rmdir() 函数
    PHP ftp_rename() 函数
    PHP ftp_rawlist() 函数
    PHP ftp_raw() 函数
    PHP ftp_pwd() 函数
    PHP ftp_put() 函数
    PHP ftp_pasv() 函数
    PHP ftp_nlist() 函数
    PHP ftp_nb_get() 函数
    PHP ftp_nb_fget() 函数
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4451612.html
Copyright © 2011-2022 走看看