[BZOJ2244][SDOI2011]拦截导弹-CDQ分治-树状数组

本文介绍了一种算法,用于计算在导弹拦截系统中,各导弹被成功拦截的概率。通过多维偏序关系处理,利用CDQ分治算法和树状数组进行高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

拦截导弹

Description

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度、并且能够拦截任意速度的导弹,但是以后每一发炮弹都不能高于前一发的高度,其拦截的导弹的飞行速度也不能大于前一发。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
在不能拦截所有的导弹的情况下,我们当然要选择使国家损失最小、也就是拦截导弹的数量最多的方案。但是拦截导弹数量的最多的方案有可能有多个,如果有多个最优方案,那么我们会随机选取一个作为最终的拦截导弹行动蓝图。
我方间谍已经获取了所有敌军导弹的高度和速度,你的任务是计算出在执行上述决策时,每枚导弹被拦截掉的概率。

Input

第一行包含一个正整数n,表示敌军导弹数量;
下面 行按顺序给出了敌军所有导弹信息:
第i+1行包含2个正整数hi和vi,分别表示第 枚导弹的高度和速度。

Output

输出包含两行。
第一行为一个正整数,表示最多能拦截掉的导弹数量;
第二行包含n个0到1之间的实数,第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程序!

Source

第一轮day2


居然会爆long long,用double存才能过……

(╯‵□′)╯︵┻━┻


思路:
把时间翻转,和高度、速度一起看成三维。
那么这就是个多维偏序关系的最长不上升子序列问题。

多维咱们用CDQ即可,按时间排序,分治高度,按速度维护树状数组。
考虑做两次CDQ,对于每个点,统计出以它作为最长不上升子序列结尾的最优方案、以它作为最长不上升子序列开头的最优方案,以及它们的方案数。

如果以一个点结尾的最优方案+以这个点开头的最优方案-1与总体最优方案的值相等,那么这个点可以出现在最优方案中。
此时,这个点的出现概率为(结尾最优方案数*开头最优方案数)/总方案数。

然后就做完了~
为了方便写了很多STL_(:з」∠)_

#include<bits/stdc++.h>
using namespace std;

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || '9'<ch){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
    return x*f;
}

typedef double db;
const int N=1e5+9;

template<typename T>inline bool chkmin(T &a,T b){if(a>b){a=b;return 1;}return 0;}
template<typename T>inline bool chkmax(T &a,T b){if(a<b){a=b;return 1;}return 0;}

int n,m;
db fx[2][N],fv[2][N];

struct node
{
    int t,h,v;
    bool operator < (node o)const
    {
        if(h!=o.h)
            return h<o.h;
        return v<o.v;
    }
}a[N],tmp[N];

map<int,int> ha;

inline bool cmpt(node a,node b){return a.t<b.t;}
inline bool cmph(node a,node b){return a.h<b.h;}

namespace bit
{
    int bmax[N<<1];db bcnt[N<<1];

    inline void add(int x,int v,db c)
    {
        for(int i=x;i<=m;i+=i&-i)
            if(chkmax(bmax[i],v))
                bcnt[i]=c;
            else if(bmax[i]==v)
                bcnt[i]+=c;
    }

    inline int qmax(int x)
    {
        int ret=0;
        for(int i=x;i;i-=i&-i)
            chkmax(ret,bmax[i]);
        return ret;
    }

    inline db qsum(int x,int v)
    {
        db ret=0;
        for(int i=x;i;i-=i&-i)
            if(bmax[i]==v)
                ret+=bcnt[i];
        return ret;
    }

    inline void del(int x)
    {
        for(int i=x;i<=m;i+=i&-i)
            bmax[i]=bcnt[i]=0;
    }
}

inline void cdq(int l,int r,int d)
{
    if(l==r)return;
    int mid=l+r>>1,lp,rp;
    cdq(l,mid,d);
    copy(a+mid+1,a+r+1,tmp+mid+1);
    sort(a+mid+1,a+r+1,cmph);

    db *f=fx[d],*g=fv[d];
    for(lp=l,rp=mid+1;rp<=r;rp++)
    {
        while(lp<=mid && a[lp].h<=a[rp].h)
            bit::add(a[lp].v,f[a[lp].t],g[a[lp].t]),lp++;
        db mxv=bit::qmax(a[rp].v);
        if(chkmax(f[a[rp].t],mxv+1))
            g[a[rp].t]=bit::qsum(a[rp].v,mxv);
        else if(f[a[rp].t]==mxv+1)
            g[a[rp].t]+=bit::qsum(a[rp].v,mxv);
    }
    for(lp--;lp>=l;lp--)
        bit::del(a[lp].v);

    copy(tmp+mid+1,tmp+r+1,a+mid+1);
    cdq(mid+1,r,d);
    merge(a+l,a+mid+1,a+mid+1,a+r+1,tmp+l);
    copy(tmp+l,tmp+r+1,a+l);
}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        a[i].t=n-i+1;
        ha[a[i].h=read()];
        ha[a[i].v=read()];
    }

    reverse(a+1,a+n+1);
    for(int i=1;i<=n;i++)
        fx[0][i]=fx[1][i]=fv[0][i]=fv[1][i]=1;
    for(map<int,int>::iterator it=ha.begin();it!=ha.end();it++)
        (*it).second=++m;
    for(int i=1;i<=n;i++)
    {
        a[i].h=ha[a[i].h];
        a[i].v=ha[a[i].v];
    }

    cdq(1,n,0);
    for(int i=1;i<=n;i++)
        a[i].t=n-a[i].t+1,a[i].h=m-a[i].h+1,a[i].v=m-a[i].v+1;
    sort(a+1,a+n+1,cmpt);
    cdq(1,n,1);
    reverse(fx[0]+1,fx[0]+n+1);
    reverse(fv[0]+1,fv[0]+n+1);

    db ans=0,sum=0;
    for(int i=1;i<=n;i++)
    {
        if(chkmax(ans,fx[0][i]))
            sum=fv[0][i];
        else if(ans==fx[0][i])
            sum+=fv[0][i];
    }

    printf("%.0f\n",ans);
    for(int i=1;i<=n;i++)
    {
        if(fx[0][i]+fx[1][i]-1!=ans)
            printf("%.5f ",0.0);
        else
            printf("%.5f ",(fv[0][i]*fv[1][i])/sum);
    }
    puts("");
    return 0;
}
内容概要:本文详细探讨了基于MATLAB/SIMULINK的多载波无线通信系统仿真及性能分析,重点研究了以OFDM为代表的多载波技术。文章首先介绍了OFDM的基本原理和系统组成,随后通过仿真平台分析了不同调制方式的抗干扰性能、信道估计算法对系统性能的影响以及同步技术的实现与分析。文中提供了详细的MATLAB代码实现,涵盖OFDM系统的基本仿真、信道估计算法比较、同步算法实现和不同调制方式的性能比较。此外,还讨论了信道特征、OFDM关键技术、信道估计、同步技术和系统级仿真架构,并提出了未来的改进方向,如深度学习增强、混合波形设计和硬件加速方案。; 适合人群:具备无线通信基础知识,尤其是对OFDM技术有一定了解的研究人员和技术人员;从事无线通信系统设计与开发的工程师;高校通信工程专业的高年级本科生和研究生。; 使用场景及目标:①理解OFDM系统的工作原理及其在多径信道环境下的性能表现;②掌握MATLAB/SIMULINK在无线通信系统仿真中的应用;③评估不同调制方式、信道估计算法和同步算法的优劣;④为实际OFDM系统的设计和优化提供理论依据和技术支持。; 其他说明:本文不仅提供了详细的理论分析,还附带了大量的MATLAB代码示例,便于读者动手实践。建议读者在学习过程中结合代码进行调试和实验,以加深对OFDM技术的理解。此外,文中还涉及了一些最新的研究方向和技术趋势,如AI增强和毫米波通信,为读者提供了更广阔的视野。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值