• BZOJ 2244 [SDOI2011]拦截导弹 ——CDQ分治


    三维偏序,直接CDQ硬上。

    正反两次CDQ统计结尾的方案数,最后统计即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=i;--i)
    #define ll long double
    #define maxn 50005
    struct Mis{
        int id,h,v;
        void print()
        {
            printf("The ID %d High %d Speed %d
    ",id,h,v);
        }
    }a[maxn];
    int f[maxn][2],n,h[maxn],v[maxn],htop,vtop;
    ll g[maxn][2];
    bool cmp1(Mis a,Mis b){return a.id<b.id;}
    bool cmp2(Mis a,Mis b){return a.h<b.h;}
    int mx[maxn]; ll cnt[maxn];
    void add(int x,int f,ll g)
    {
        for (;x<maxn;x+=x&(-x))
            if (mx[x]==f) cnt[x]+=g;
            else if (mx[x]<f) mx[x]=f,cnt[x]=g;
            else break;
    }
    int qmx(int x)
    {
        int ret=0;
        for (;x;x-=x&(-x)) ret=max(ret,mx[x]);
        return ret;
    }
    ll qcnt(int x,int m)
    {
        ll ret=0;
        for (;x;x-=x&(-x))
            if (mx[x]==m) ret+=cnt[x];
        return ret;
    }
    void del(int x)
    {
        for (;x<maxn;x+=x&(-x)) cnt[x]=mx[x]=0;
    }
    void CDQ(int l,int r,int flag)
    {
        if (l==r)
        {
            if (f[a[l].id][flag]<1)
            {
                g[a[l].id][flag]=f[a[l].id][flag]=1;
            }
            return ;
        }
        int mid=l+r>>1;
        sort(a+l,a+r+1,cmp1);
        CDQ(l,mid,flag);
        sort(a+l,a+mid+1,cmp2);
        sort(a+mid+1,a+r+1,cmp2);
        int pl=l;
        F(i,mid+1,r)
        {
            while (a[pl].h<=a[i].h&&pl<=mid) add(a[pl].v,f[a[pl].id][flag],g[a[pl].id][flag]),pl++;
            int tmp=qmx(a[i].v)+1;
            if (tmp==1) continue;
            if (tmp>f[a[i].id][flag])
            {
                f[a[i].id][flag]=tmp;
                g[a[i].id][flag]=qcnt(a[i].v,tmp-1);
            }
            else if (tmp==f[a[i].id][flag])
                g[a[i].id][flag]+=qcnt(a[i].v,tmp-1);
        }
        F(i,l,pl-1) del(a[i].v);
        CDQ(mid+1,r,flag);
    }
    void print()
    {
        int ans=0;
        F(i,1,n) ans=max(ans,f[i][0]);
        printf("%d
    ",ans);
        ll sum=0;
        F(i,1,n) if (f[i][0]==ans) sum+=g[i][0]*g[n-i+1][1];
        F(i,1,n)
        {
            if (f[i][0]+f[n-i+1][1]-1==ans) printf("%.5Lf ",g[i][0]*g[n-i+1][1]/sum);
            else printf("0 ");
        }
    }
    int main()
    {
        scanf("%d",&n);htop=vtop=n;
        F(i,1,n)
        {
            scanf("%d%d",&a[i].h,&a[i].v);
            a[i].id=i;h[i]=a[i].h;v[i]=a[i].v;
        }
        sort(h+1,h+htop+1); sort(v+1,v+vtop+1);
        htop=unique(h+1,h+htop+1)-h-1; vtop=unique(v+1,v+vtop+1)-v-1;
        F(i,1,n)
        {
            a[i].h=lower_bound(h+1,h+htop+1,a[i].h)-h;
            a[i].v=lower_bound(v+1,v+vtop+1,a[i].v)-v;
        }
        F(i,1,n)
        {
            a[i].h=htop-a[i].h+1;
            a[i].v=vtop-a[i].v+1; 
        }
        CDQ(1,n,0);
        F(i,1,n)
        {
            a[i].id=n-a[i].id+1;
            a[i].v=vtop-a[i].v+1;
            a[i].h=htop-a[i].h+1;
        }
        CDQ(1,n,1);
        print();
    }
    

      

  • 相关阅读:
    iOS 键盘回收实现步骤
    Xcode 向6.0以后版本添加iOS开发空白模板
    popViewControllerAnimated 后,对页面内UITableView 内数据刷新
    指针,数组,字符串
    求解 s = (1*1)!+(2*2)! + (3*3)!+...+(n*n)! (C语言)
    sqlserver分页;mysql分页;orcale分页 的sql 查询语句
    实现strlen,strcpy,strcat,strcmp同功能的函数stringLength,stringCopy,stringCatch,stringCompare
    对字符串(英文)从小到大排序
    二维数组名作为实参或者形参
    联合与枚举 、 高级指针 、 C语言标准库(一)
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6607073.html
Copyright © 2020-2023  润新知