zoukankan      html  css  js  c++  java
  • BZOJ:2244: [SDOI2011]拦截导弹

    问题:

      printf("%.5f ",0):为什么错了?

    注意:

      初始值很重要

    题解:

    三维偏序问题;

    记录从前往后最长上升子序列长度pref,条数preg

    从后往前suff,sufg

    如果对于某个点pref+suff==ans-1,那么打掉它的概率 preg*sufg/tot

    Wa了好多次QWQ

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define lowbit(x) x&(-x)
    using namespace std;
    typedef long long Lint;
    const int maxn=3000009;
    
    int n;
    int ans;
    
    double tot;
    int pref[maxn];
    double preg[maxn];
    int suff[maxn];
    double sufg[maxn];
    
    struct Missile{
    	int x,z,y,f;
    	double g;
    }a[maxn];
    
    int b[maxn],nn;
    
    int c[maxn];
    double d[maxn];
    int add(int x,int val,double q){
    	while(x<=nn){
    		if(val>c[x]){
    			c[x]=val;
    			d[x]=q;
    		}else if(val==c[x]){
    			d[x]+=q;
    		}
    		x+=lowbit(x);
    	}
    }
    int refresh(int x){
    	while(x<=nn){
    		c[x]=d[x]=0;
    		x+=lowbit(x);
    	}
    }
    int querymax(int x){
    	int ret=0;
    	while(x){
    		ret=max(ret,c[x]);
    		x-=lowbit(x);
    	}
    	return ret;
    }
    double querysum(int x,int val){
    	double ret=0;
    	while(x){
    		if(c[x]==val){
    			ret+=d[x];
    		}
    		x-=lowbit(x);
    	}
    	return ret;
    }
    
    int cmpx(const Missile &tmp1,const Missile &tmp2){
    	return tmp1.x<tmp2.x;
    }
    int cmpy(const Missile &tmp1,const Missile &tmp2){
    	if(tmp1.y==tmp2.y)return tmp1.z<tmp2.z;
    	else return tmp1.y<tmp2.y;
    }
    int cdq(int l,int r){
    	if(l==r)return 0;
    	int mid=(l+r)>>1;
    	cdq(l,mid);
    	int t1=l,t2=mid+1;
    	sort(a+l,a+mid+1,cmpy);
    	sort(a+mid+1,a+r+1,cmpy);
    	while(t2<=r){
    		while((t1<=mid)&&(a[t1].y<=a[t2].y)){
    			add(a[t1].z,a[t1].f,a[t1].g);
    			++t1;
    		}
    		int tmp=querymax(a[t2].z)+1;
    		if(tmp>a[t2].f){
    			a[t2].f=tmp;
    			a[t2].g=querysum(a[t2].z,tmp-1);
    		}else if(tmp==a[t2].f){
    			a[t2].g+=querysum(a[t2].z,tmp-1);
    		}
    		++t2;
    	}
    	for(int i=l;i<=mid;++i){
    		refresh(a[i].z);
    	}
    	sort(a+mid+1,a+r+1,cmpx);
    	cdq(mid+1,r);
    }
    
    int work1(){
    	for(int i=1;i<=n;++i){
    		a[i].y=-a[i].y;
    		a[i].z=nn-a[i].z+1;
    		a[i].f=a[i].g=1;
    	}
    	cdq(1,n);
    	for(int i=1;i<=n;++i){
    		ans=max(ans,a[i].f);
    		pref[a[i].x]=a[i].f;
    		preg[a[i].x]=a[i].g;
    	}
    	for(int i=1;i<=n;++i){
    		if(a[i].f==ans)tot=tot+a[i].g;
    	}
    }
    int work2(){
    	for(int i=1;i<=n;++i){
    		a[i].x=-a[i].x;
    		a[i].y=-a[i].y;
    		a[i].z=nn-a[i].z+1;
    		a[i].f=a[i].g=1;
    	}
    	sort(a+1,a+1+n,cmpx);
    	cdq(1,n);
    	for(int i=1;i<=n;++i){
    		suff[-a[i].x]=a[i].f;
    		sufg[-a[i].x]=a[i].g;
    	}
    }
    int Getans(){
    	printf("%d
    ",ans);
    	for(int i=1;i<=n;++i){
    		if(pref[i]+suff[i]-1==ans){
    			printf("%.5f ",preg[i]*sufg[i]/tot);
    		}else{
    			printf("%d ",0);
    		}
    	}
    }
    
    int minit(){
    	tot=0;
    	ans=0;
    	for(int i=0;i<=n;++i){
    		d[i]=c[i]=0;
    	}
    }
    
    int main(){
    //	freopen("Misslie.in","r",stdin);
    //	freopen("Misslie.out","w",stdout);
    	
    	scanf("%d",&n);
    	minit();
    	for(int i=1;i<=n;++i){
    		scanf("%d%d",&a[i].y,&a[i].z);
    		a[i].x=i;
    		b[i]=a[i].z;
    	}
    	sort(b+1,b+1+n);
    	nn=unique(b+1,b+1+n)-b-1;
    	for(int i=1;i<=n;++i){
    		a[i].z=lower_bound(b+1,b+1+nn,a[i].z)-b;
    	}
    	
    	work1();
    	work2();
    	
    	Getans();
    	return 0;
    }
    

      

    自己还是太辣鸡了
  • 相关阅读:
    使用XMLReader读XML
    C#命名空间大全详细教程
    C# using 三种使用方式
    SVN服务器搭建
    简单的自定义Session
    python学习第十八天 --错误&异常处理
    锁的等级:方法锁、实例锁、类锁
    java线程池如何合理的设置大小
    挖掘两个Integer对象的swap的内幕
    实现线程同步的方式
  • 原文地址:https://www.cnblogs.com/zzyer/p/8179292.html
Copyright © 2011-2022 走看看