zoukankan      html  css  js  c++  java
  • bzoj2244[SDOI2011]拦截导弹

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

    第$i$个导弹看成一个三元组$(i,h_i,v_i)$

    其实就是最长上升子序列的问题。

    我们分别求以第$i$个导弹为结尾的最长上升子序列的长度和个数,以及以第$i$个导弹为开头的最长上升子序列的长度和个数。

    下面以求以第$i$个导弹为结尾的最长上升子序列的长度和个数为例。

    记以第$i$个导弹结尾的最长上升子序列长度为$f[i]$,则:

    $$f[i]=Max{f[j]|j<i,h[j]geq h[i],v[j]geq v[i]}+1$$

    所以第1问就是三维偏序,用CDQ分治解决。

    第一维由分治的时候左边小于右边保证;

    第二维由排序保证;

    第三维由数据结构保证;

    看程序应该会比较好理解。

    记以第$i$个导弹结尾的最长上升子序列长度为$g[i]$,则:

    $$g[i]=sum g[j](f[j]+1=f[i],j<i,h[j]geq h[i],v[j]geq v[i])$$

    我们可以先按f排序,然后分层DP,还是用CDQ分治。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<fstream>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<vector>
    #include<functional>
    #include<deque>
    #include<cctype>
    #include<climits>
    #include<complex>
    //#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
     
    using namespace std;
    
    typedef long long LL;
    typedef double DB;
    typedef pair<int,int> PII;
    typedef complex<DB> CP;
    
    #define mmst(a,v) memset(a,v,sizeof(a))
    #define mmcy(a,b) memcpy(a,b,sizeof(a))
    #define fill(a,l,r,v) fill(a+l,a+r+1,v)
    #define re(i,a,b)  for(i=(a);i<=(b);i++)
    #define red(i,a,b) for(i=(a);i>=(b);i--)
    #define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
    #define fi first
    #define se second
    #define m_p(a,b) make_pair(a,b)
    #define p_b(a) push_back(a)
    #define SF scanf
    #define PF printf
    #define two(k) (1<<(k))
    
    template<class T>inline T sqr(T x){return x*x;}
    template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
    template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}
    
    inline int sgn(DB x){if(abs(x)<1e-9)return 0;return(x>0)?1:-1;}
    const DB Pi=acos(-1.0);
    
    int gint()
      {
            int res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    LL gll()
      {
          LL res=0;bool neg=0;char z;
            for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
            if(z==EOF)return 0;
            if(z=='-'){neg=1;z=getchar();}
            for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
            return (neg)?-res:res; 
        }
    
    const int maxn=50000;
    
    int n,ny,nz;
    struct Ta{int x,y,z,f,flag;DB g;}a[maxn+100];
    int bak[maxn+100];
    
    int f1[maxn+100],f2[maxn+100];
    DB g1[maxn+100],g2[maxn+100];
    int ans;
    
    bool cmpx(Ta a,Ta b){return a.x<b.x;}
    bool cmpyx(Ta a,Ta b){return a.y!=b.y?a.y<b.y:a.x<b.x;}//注意y相同时,x小的在前面!!! 
    bool cmpf(Ta a,Ta b){return a.f<b.f;}
    
    #define lowbit(a) ((a)&(-a))
    namespace TREE1
      {
            int tree[maxn+100];
            void update(int a,int v){for(;a<=n;a+=lowbit(a))upmax(tree[a],v);}
            int ask(int a){int res=0;for(;a>=1;a-=lowbit(a))upmax(res,tree[a]);return res;}
            void clear(int a){for(;a<=n;a+=lowbit(a))tree[a]=0;}
      }
    void CDQf(int l,int r)
      {
          if(l==r){upmax(a[l].f,1);return;}
          int i,mid=(l+r)/2;
          CDQf(l,mid);
          sort(a+l,a+r+1,cmpyx);
          re(i,l,r)if(a[i].x<=mid)TREE1::update(a[i].z,a[i].f);else upmax(a[i].f,TREE1::ask(a[i].z)+1);
          re(i,l,r)if(a[i].x<=mid)TREE1::clear(a[i].z);
          sort(a+l,a+r+1,cmpx);
          CDQf(mid+1,r);
      }
    
    namespace TREE2
      {
          DB tree[maxn+100];
          void update(int a,DB v){for(;a<=n;a+=lowbit(a))tree[a]+=v;}
          DB ask(int a){DB res=0;for(;a>=1;a-=lowbit(a))res+=tree[a];return res;}
          void clear(int a){for(;a<=n;a+=lowbit(a))tree[a]=0.0;}
      }
    void CDQg(int l,int r)
      {
          if(l==r)return;
          int i,mid=(l+r)/2;
          CDQg(l,mid);
          sort(a+l,a+r+1,cmpyx);
          re(i,l,r)
            {
                if(a[i].x<=mid && a[i].flag) TREE2::update(a[i].z,a[i].g);
                if(a[i].x>mid && !a[i].flag) a[i].g+=TREE2::ask(a[i].z);
            }
          re(i,l,r)if(a[i].x<=mid && a[i].flag) TREE2::clear(a[i].z);
          sort(a+l,a+r+1,cmpx);
          CDQg(mid+1,r);
      }
    
    int tmpx[maxn+100];
    void solve()
      {
          int i,j,l1,r1,l2,r2;
          re(i,1,n)a[i].f=0,a[i].g=0.0;
          CDQf(1,n);
          sort(a+1,a+n+1,cmpf);
          for(l1=r1=1;r1<n && a[r1+1].f==a[l1].f;r1++);
          re(i,l1,r1)a[i].g=1;
          for(;r1<n;l1=l2,r1=r2)
            {
                for(l2=r2=r1+1;r2<n && a[r2+1].f==a[l2].f;r2++);
                re(i,l1,r1)a[i].flag=1;
                sort(a+l1,a+r2+1,cmpx);
                re(i,l1,r2)tmpx[i]=a[i].x,a[i].x=i;
                CDQg(l1,r2);
                re(i,l1,r2)a[i].x=tmpx[i];
                sort(a+l1,a+r2+1,cmpf);
                re(i,l1,r1)a[i].flag=0;
            }
          sort(a+1,a+n+1,cmpx);
      }
    
    int ans1;
    DB ans2;
    
    int main()
      {
          freopen("bzoj2244.in","r",stdin);
          freopen("bzoj2244.out","w",stdout);
            int i;
            n=gint();
            re(i,1,n)a[i].x=i,a[i].y=gint(),a[i].z=gint();
            
            ny=0;
            re(i,1,n)bak[++ny]=a[i].y;
            sort(bak+1,bak+ny+1);
            ny=unique(bak+1,bak+ny+1)-bak-1;
            re(i,1,n)a[i].y=ny-(lower_bound(bak+1,bak+ny+1,a[i].y)-bak)+1;
            nz=0;
            re(i,1,n)bak[++nz]=a[i].z;
            sort(bak+1,bak+nz+1);
            nz=unique(bak+1,bak+nz+1)-bak-1;
            re(i,1,n)a[i].z=nz-(lower_bound(bak+1,bak+nz+1,a[i].z)-bak)+1;
            
            solve();
            re(i,1,n)f1[i]=a[i].f,g1[i]=a[i].g;
            
            re(i,1,n)a[i].x=n-a[i].x+1,a[i].y=ny-a[i].y+1,a[i].z=nz-a[i].z+1;
            re(i,1,n/2)swap(a[i],a[n-i+1]);
        
            solve();
            re(i,1,n)a[i].x=n-a[i].x+1,a[i].y=ny-a[i].y+1,a[i].z=nz-a[i].z+1;
            re(i,1,n/2)swap(a[i],a[n-i+1]);
            re(i,1,n)f2[i]=a[i].f,g2[i]=a[i].g;
            
            re(i,1,n)upmax(ans1,f1[i]);
            re(i,1,n)if(f1[i]==ans1)ans2+=g1[i];
            PF("%d
    ",ans1);
            re(i,1,n)if(f1[i]+f2[i]-1!=ans1 || sgn(ans2)==0)PF("0.00000 ");else PF("%0.5lf ",g1[i]*g2[i]/ans2);
            return 0;
        }
    View Code
  • 相关阅读:
    python三级菜单
    python购物车
    crontab计划任务
    shell脚本相关关系、浮点、循环
    find及其他命令
    awk命令
    sed命令
    linux正则表达式
    shell脚本编写nginx部署脚本
    shell脚本编写监控内存并发送邮件
  • 原文地址:https://www.cnblogs.com/maijing/p/4857729.html
Copyright © 2011-2022 走看看