码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ2244][SDOI2011]拦截导弹

时间:2018-03-14 19:38:34      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:就是   .com   ==   blog   ret   0.00   ++   resid   void   

bzoj
luogu

sol

某一枚导弹被拦截的概率等于这一枚导弹被拦截的方案数,也就是这枚导弹参与构成最长不上升子序列的方案数,除以最长不上升子序列的总方案数。总方案数会爆long long,但是可以用double存(雾)
从前往后做一遍最长不上升子序列,再从后往前做一遍最长不下降子序列,并且求方案数。一枚导弹被拦截的方案数等于前后的方案数的乘积。如果一枚导弹的前后\(dp\)值相加-1不等于LIS,那么这枚导弹就不可能出现在最长不上升子序列里面,因此答案为0。
树套树维护\(dp\)值同时统计方案数。

code

#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 5e4+5;
struct Data{
    int f;double g;
    Data operator + (const Data &b) const
        {
            if (f>b.f) return (Data){f,g};
            if (f<b.f) return (Data){b.f,b.g};
            return (Data){f,g+b.g};
        }
}dp[2][N];
struct president_tree{int ls,rs;Data v;}t[N*150];
int n,a[N],b[N],o1[N],o2[N],len1,len2,rt[N],tot,ans;double cnt;
void modify(int &x,int l,int r,int p,Data v)
{
    if (!x) x=++tot;
    t[x].v=t[x].v+v;
    if (l==r) return;int mid=l+r>>1;
    if (p<=mid) modify(t[x].ls,l,mid,p,v);
    else modify(t[x].rs,mid+1,r,p,v);
}
Data query(int x,int l,int r,int ql,int qr)
{
    if (!x||l>=ql&&r<=qr) return t[x].v;
    int mid=l+r>>1;
    if (qr<=mid) return query(t[x].ls,l,mid,ql,qr);
    if (ql>mid) return query(t[x].rs,mid+1,r,ql,qr);
    return query(t[x].ls,l,mid,ql,qr)+query(t[x].rs,mid+1,r,ql,qr);
}
int main()
{
    n=gi();
    for (int i=1;i<=n;++i) o1[++len1]=a[i]=gi(),o2[++len2]=b[i]=gi();
    sort(o1+1,o1+len1+1);len1=unique(o1+1,o1+len1+1)-o1-1;
    sort(o2+1,o2+len2+1);len2=unique(o2+1,o2+len2+1)-o2-1;
    for (int i=1;i<=n;++i)
    {
        a[i]=lower_bound(o1+1,o1+len1+1,a[i])-o1;
        b[i]=lower_bound(o2+1,o2+len2+1,b[i])-o2;
    }
    for (int i=1;i<=n;++i)
    {
        a[i]=len1-a[i]+1;dp[0][i]=(Data){0,1};
        for (int j=a[i];j;j-=j&-j)
            dp[0][i]=dp[0][i]+query(rt[j],1,n,b[i],len2);
        dp[0][i].f++;
        for (int j=a[i];j<=len1;j+=j&-j)
            modify(rt[j],1,n,b[i],dp[0][i]);
    }
    for (int i=1;i<=len1;++i) rt[i]=0;
    for (int i=1;i<=tot;++i) t[i].ls=t[i].rs=0,t[i].v.f=0,t[i].v.g=0;tot=0;
    for (int i=n;i;--i)
    {
        a[i]=len1-a[i]+1;dp[1][i]=(Data){0,1};
        for (int j=a[i];j;j-=j&-j)
            dp[1][i]=dp[1][i]+query(rt[j],1,n,1,b[i]);
        dp[1][i].f++;
        for (int j=a[i];j<=len1;j+=j&-j)
            modify(rt[j],1,n,b[i],dp[1][i]);
    }
    for (int i=1;i<=n;++i) ans=max(ans,dp[0][i].f+dp[1][i].f-1);
    printf("%d\n",ans);
    for (int i=1;i<=n;++i) if (dp[0][i].f==ans) cnt+=dp[0][i].g;
    for (int i=1;i<=n;++i)
        if (ans==dp[0][i].f+dp[1][i].f-1)
            printf("%.6lf ",dp[0][i].g*dp[1][i].g/cnt);
        else printf("0.000000 ");
    puts("");return 0;
}

[BZOJ2244][SDOI2011]拦截导弹

标签:就是   .com   ==   blog   ret   0.00   ++   resid   void   

原文地址:https://www.cnblogs.com/zhoushuyu/p/8569526.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!