zoukankan      html  css  js  c++  java
  • bzoj 2244 [SDOI2011]拦截导弹(DP+CDQ分治+BIT)

    【题目链接】

        http://www.lydsy.com/JudgeOnline/problem.php?id=2244

    【题意】

        给定n个二元组,求出最长不上升子序列和各颗导弹被拦截的概率。

    【思路】

        DP+CDQ分治+BIT

        先把序列反转一下,lis求起来方便。

        对于第一问,我们要求的是

            f[i]=max{ f[j] },j<i,x[j]<x[i],y[j]<y[i]

        发现需要满足的条件就是一个三维偏序,可以用CDQ分治求解

        不难发现第二问其实就等于:一颗导弹所在的lis数/总的lis数。一个导弹所在的lis必须包含自己,所以我们设g[i]表示以i为结尾的lis总数,则有转移式:

            g[i]=sigma{ g[j] }, j<i,x[j]<x[i],y[j]<y[i],f[j]+1=f[i]

        依旧可以用CDQ分治求。注意到最后的一个f的关系,这时候只需要统计出之前的最大lis值再与f相比较就可以了(蒟蒻的我一直苦思冥想。。。

        相似的可以求出g’f’。都是g f的相反定义,即以i开头的…

        奇技淫巧:我们可以在反转一下并对序列取一下反,这样就都可以套用函数辣。貌似离散化之后跑得飞快,一跃直上rk3

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      5 #define FOR(a,b,c) for(int a=b;a<=c;a++)
      6 using namespace std;
      7 
      8 const int N = 1e5+10;
      9 
     10 struct Node {
     11     int id,x,y;
     12     bool operator<(const Node& rhs)const {
     13         return x<rhs.x||(x==rhs.x&&y<rhs.y);
     14     }
     15 }q[N],t[N];
     16 bool cmp(const Node& a,const Node& b)
     17 {
     18     return a.id<b.id;
     19 }
     20 
     21 int f[2][N]; double g[2][N],ans[N];
     22 int hash[N],tot,n;
     23 
     24 
     25 int read()
     26 {
     27     char c=getchar(); int x=0; int f=1;
     28     while(!isdigit(c)){if(c=='-')f=-1; c=getchar();}
     29     while(isdigit(c)) x=x*10+c-'0',c=getchar();
     30     return x*f;
     31 }
     32 
     33 int t_f[N],tag[N],T; double t_g[N];
     34 void add(int x,int f,double g)
     35 {
     36     for(;x<=tot;x+=x&-x) {
     37         if(tag[x]!=T) {tag[x]=T;t_f[x]=0;t_g[x]=0;}
     38         if(f>t_f[x]){t_f[x]=f;t_g[x]=g;}
     39         else if(f==t_f[x]) t_g[x]+=g;
     40     }
     41 }
     42 void query(int x,int& mx,double& sum)
     43 {
     44     mx=0; sum=0.0;
     45     for(;x;x-=x&-x) if(tag[x]==T){
     46         if(t_f[x]>mx) {
     47             mx=t_f[x]; sum=t_g[x];
     48         } else if(t_f[x]==mx)
     49             sum+=t_g[x];
     50     }
     51 }
     52 
     53 void solve(int l,int r,int ty)
     54 {
     55     if(l==r) {
     56         if(!f[ty][l]){
     57             f[ty][l]=1; g[ty][l]=1;
     58         }
     59         return ;
     60     }
     61     int mid=(l+r)>>1;
     62     int l1=l,l2=mid+1,i,j,cnt=0;
     63     for(i=l;i<=r;i++) {
     64         if(q[i].id<=mid) t[l1++]=q[i];
     65         else t[l2++]=q[i];
     66     }
     67     memcpy(q+l,t+l,sizeof(Node)*(r-l+1));
     68     solve(l,mid,ty);
     69     T++;
     70     sort(q+mid+1,q+r+1);
     71     for(i=mid+1,j=l;i<=r;i++)
     72     {
     73         int id;
     74         for(;j<=mid&&q[j].x<=q[i].x;j++) {
     75             id=q[j].id; cnt++;
     76             add(q[j].y,f[ty][id],g[ty][id]);
     77         }
     78         int mx; double sum;
     79         query(q[i].y,mx,sum);
     80         id=q[i].id;
     81         if(mx>0) {
     82             if(mx+1>f[ty][id]) {
     83                 f[ty][id]=mx+1; g[ty][id]=sum;
     84             } else if(mx+1==f[ty][id]) {
     85                 g[ty][id]+=sum;
     86             }
     87         }
     88     }
     89     solve(mid+1,r,ty);
     90     l1=l,l2=mid+1; int now=l;
     91     while(l1<=mid||l2<=r) {
     92         if(l2>r||l1<=mid&&q[l1]<q[l2]) t[now++]=q[l1++];
     93         else t[now++]=q[l2++];
     94     }
     95     memcpy(q+l,t+l,sizeof(Node)*(r-l+1));
     96 }
     97 
     98 int main()
     99 {
    100     //freopen("in.in","r",stdin);
    101     //freopen("out.out","w",stdout);
    102     n=read();
    103     int mxx=0;
    104     FOR(i,1,n)
    105     {
    106         q[i].x=read(),q[i].y=read();
    107         hash[i]=q[i].y;
    108         mxx=max(mxx,q[i].x);
    109     }
    110     sort(hash+1,hash+n+1);
    111     tot=unique(hash+1,hash+n+1)-hash-1;
    112     FOR(i,1,n)
    113         q[i].y=lower_bound(hash+1,hash+tot+1,q[i].y)-hash;
    114     reverse(q+1,q+n+1);
    115     FOR(i,1,n) q[i].id=i;
    116     solve(1,n,0);
    117 
    118     sort(q+1,q+n+1,cmp);
    119     reverse(q+1,q+n+1);
    120     FOR(i,1,n)
    121         q[i].x=mxx-q[i].x+1,q[i].y=tot-q[i].y+1,
    122         q[i].id=i;
    123     solve(1,n,1);
    124     int mx=0; double sum=0;
    125     FOR(i,1,n) {
    126         int tmp=f[0][i];
    127         if(tmp>mx) {
    128             mx=tmp; sum=g[0][i]*g[1][n-i+1];
    129         } else if(tmp==mx)
    130             sum+=g[0][i]*g[1][n-i+1];
    131     }
    132     printf("%d
    ",mx);
    133     for(int i=n;i;i--) {
    134         if(f[0][i]+f[1][n-i+1]-1==mx) {
    135             ans[i]=(g[0][i]*g[1][n-i+1])/sum;
    136         } else ans[i]=0;
    137     }
    138     for(int i=n;i>1;i--) printf("%.5lf ",ans[i]);
    139     printf("%.5lf",ans[1]);
    140     return 0;
    141 }
  • 相关阅读:
    Leetcode 238. Product of Array Except Self
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 290. Word Pattern
    Leetcode 205. Isomorphic Strings
    Leetcode 107. Binary Tree Level Order Traversal II
    Leetcode 102. Binary Tree Level Order Traversal
    三目运算符
    简单判断案例— 分支结构的应用
    用switch判断月份的练习
    java基本打印练习《我行我素购物系统》
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5262572.html
Copyright © 2011-2022 走看看