bzoj2244: [SDOI2011]拦截导弹

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2244: [SDOI2011]拦截导弹相关的知识,希望对你有一定的参考价值。

传送门

我tmd的连三维偏序都不会写了。。

我tmd已经是个废宸了。。

似乎decdq分治的bug永远是我的痛。。

三维偏序,三维倒过来再跑一遍,看一个点前后加起来是否等于答案。

算方案用了线段树,跑得贼慢。优秀的人都会用树状数组,不会。

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=5e4+7;
typedef long long LL;
using namespace std;
int n,ls[N],sz,f[N],ff[N],mxans;
double g[N],ans[N],gg[N];

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
}

struct node {
    int x,y,ti,id;
}p[N];

bool CMP(const node&A,const node&B) {
    return A.ti<B.ti;
}

bool cmp(const node &A,const node&B) {
    return A.x>B.x||(A.x==B.x&&(A.y>B.y||(A.y==B.y&&A.ti<B.ti)));    
}

#define lc x<<1
#define rc x<<1|1
#define mid ((l+r)>>1)
int mx[N<<2];
double sum[N<<2];
void update(int x,int l,int r,int pos,int fi,double gi) {
    if(l==r) { 
        if(mx[x]<fi) sum[x]=gi,mx[x]=fi;
        else if(mx[x]==fi) sum[x]+=gi; return;
    }
    if(pos<=mid) update(lc,l,mid,pos,fi,gi);
    else update(rc,mid+1,r,pos,fi,gi);
    mx[x]=max(mx[lc],mx[rc]);
    if(mx[lc]==mx[rc]) sum[x]=sum[lc]+sum[rc];
    else sum[x]=mx[lc]>mx[rc]?sum[lc]:sum[rc];
}

void qry(int x,int l,int r,int ql,int qr,int &f,double &g) {
    if(l>=ql&&r<=qr) {
        if(mx[x]+1>f) f=mx[x]+1,g=sum[x];
        else if(mx[x]+1==f) g+=sum[x]; return;
    }
    if(ql<=mid) qry(lc,l,mid,ql,qr,f,g);
    if(qr>mid) qry(rc,mid+1,r,ql,qr,f,g);
}

void clear_sg(int x,int l,int r) {
    if(!mx[x]) return;
    mx[x]=sum[x]=0;
    clear_sg(lc,l,mid); clear_sg(rc,mid+1,r);
}

void cdq(int l,int r,int f[],double g[]) {
    if(l>=r) return;
    cdq(l,mid,f,g);
    sort(p+l,p+r+1,cmp);
    for(int i=l;i<=r;i++) {
        if(p[i].ti<=mid) update(1,1,sz,p[i].y,f[p[i].id],g[p[i].id]);
        else qry(1,1,sz,p[i].y,sz,f[p[i].id],g[p[i].id]);
    } clear_sg(1,1,sz);
    sort(p+l,p+r+1,CMP);
    cdq(mid+1,r,f,g);
}

int main() {
    read(n);
    for(int i=1;i<=n;i++) {
        read(p[i].x); read(p[i].y); 
        p[i].ti=p[i].id=i;
        ls[++ls[0]]=p[i].y; 
        f[i]=g[i]=ff[i]=gg[i]=1;
    }    
    sort(ls+1,ls+ls[0]+1);
    sz=unique(ls+1,ls+ls[0]+1)-(ls+1);
    for(int i=1;i<=n;i++) 
        p[i].y=lower_bound(ls+1,ls+sz+1,p[i].y)-ls;
    cdq(1,n,f,g); 
    double ss=0;
    for(int i=1;i<=n;i++) {
        if(f[i]==mxans) ss+=g[i];
        else if(f[i]>mxans) ss=g[i],mxans=f[i];
    }
    printf("%d\n",mxans);
    for(int i=1;i<=n;i++) {
        p[i].x=1e9-p[i].x+1;
        p[i].y=sz-p[i].y+1;
        p[i].ti=n-p[i].ti+1;
    }
    sort(p+1,p+n+1,CMP);
    cdq(1,n,ff,gg);
    for(int i=1;i<=n;i++) {
        int x=p[i].id;
        if(f[x]+ff[x]-1==mxans) ans[x]=g[x]*gg[x];
        else ans[x]=0;
    }
    for(int i=1;i<=n;i++) printf("%.5lf ",ans[i]/ss);
    return 0;
}
/*
4
3 30
4 40
6 60
3 30
*/
View Code

 

以上是关于bzoj2244: [SDOI2011]拦截导弹的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 2244: [SDOI2011]拦截导弹

[BZOJ2244][SDOI2011]拦截导弹

Bzoj2244: [SDOI2011]拦截导弹

BZOJ:2244: [SDOI2011]拦截导弹

bzoj2244: [SDOI2011]拦截导弹

bzoj千题计划292:bzoj2244: [SDOI2011]拦截导弹