• 李超树——由一次NOIP模拟赛引出的车祸记


    李超树是什么?

    李超树是一种用线段树来维护直线的一种方法,因为是集训队队员李超在论文中提到,所以尊称为李超树。

    这是一次怎样的NOIP模拟赛?

    这是一次关于生死的考验.
    所以我十分认真对待。
    第一题如此:
    在这里插入图片描述
    我一下子就想到了李超树,只是把直线换成抛物线而已嘛~
    所以就开始着手。。
    由于第一次打李超树,有点尴尬。
    1个小时调对样例..
    3个小时拍完...
    然后很尴尬的发现极限数据我跑了23秒!!!
    心态没了...
    不想打比赛了...

    4000+的程序,也许只有暴力分...

    很尴尬我发现它跑到了90分...

    代码如下

    (博主很懒,没有打朴素的李超树)
    代码很丑,情况很多
    心态很崩

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define LL long long
    using namespace std;
    
    const LL maxn=5*1e5+10;
    const LL maxq=5*1e5+10;
    const LL maxX=32323+10;
    const LL XXX=-32324-100;
    
    struct root{double x,x1;};
    struct Moon{
    	LL a,b;
    }f[2*maxX*4];
    
    LL a[maxn],b[maxn];
    LL x[maxq];
    LL minx,maxx;
    LL N,Q;
    
    inline LL read(){
        LL d=0,f=1;char s=getchar();
        while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
        while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
        return d*f;
    }
    
    root cro(LL a1,LL b1,LL a2,LL b2,LL liml,LL limr){
    	LL a=a1-a2,b=b1-b2;
    	root R;
    	if(a==0){
    		R.x=0;
    		R.x1=XXX;
    		if(R.x>limr||R.x<liml) R.x=XXX;
    	}else{
    		LL delta=b*b;
    		if(delta==0){
    			R.x=(-b+sqrt(delta+0.0)+0.0)/(2*a+0.0);
    			R.x1=XXX;
    			if(R.x>limr||R.x<liml) R.x=XXX;
    		}else{
    			double R1=(-b+sqrt(delta+0.0)+0.0)/(2*a+0.0);
    			double R2=(-b-sqrt(delta+0.0)+0.0)/(2*a+0.0);
    			if(R1>R2) swap(R1,R2);
    			R.x=R1,R.x1=R2;
    			while(R.x!=XXX&&(R.x>=limr||R.x<=liml)) 
    				R.x=R.x1,R.x1=XXX;
    		}
    	}
    	return R;
    }
    
    LL val(LL a,LL b,LL x){
    	return a*x*x+b*x;
    }
    
    
    void add(LL v,LL l,LL r,LL a,LL b,LL L,LL R){
    	if(f[v].a<XXX){
    		f[v].a=a,f[v].b=b;
    		return;
    	}
    	if(f[v].a==a&&f[v].b==b) return;
    	root p=cro(a,b,f[v].a,f[v].b,l,r);
    	if(p.x==XXX){
    		int ll=l;
    		while(ll<r&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) ++ll;
    		if(val(a,b,ll)>val(f[v].a,f[v].b,ll)) f[v].a=a,f[v].b=b;
    		return;
    	}else{
    		LL nl,nr;
    		if(p.x1==XXX){
    			//交点只有一个 
    			
    			int ll=l;
    			while(ll<r&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) ++ll;
    			if(val(a,b,ll)>val(f[v].a,f[v].b,ll))
    				nl=l,nr=floor(p.x);
    			else nl=ceil(p.x),nr=r;
    			ll=r;
    			while(ll>l&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) --ll;
    			if(val(a,b,ll)>val(f[v].a,f[v].b,ll)&&nl==l&&nr==floor(p.x)){
    				f[v].a=a,f[v].b=b;
    				return;
    			}
    			if(val(a,b,ll)<val(f[v].a,f[v].b,ll)&&nl==ceil(p.x)&&nr==r) return;
    			int mid=((l+r)%2!=0)?(l+r-1)/2:(l+r)/2;
    			if(nr<=mid) add(v*2,l,mid,a,b,nl,nr);
    			else if(nl>mid) add(v*2+1,mid+1,r,a,b,nl,nr);
    			else{
    				add(v*2,l,mid,a,b,nl,mid);
    				add(v*2+1,mid+1,r,a,b,mid+1,nr);	
    			}
    		}else{
    			bool flag=0;
    			nl=ceil(p.x),nr=floor(p.x1);
    			int ll=nl;
    			while(ll<nr&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) ++ll;
    			if(val(a,b,ll)==val(f[v].a,f[v].b,ll)){
    				ll=nl;
    				while(ll>l&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) --ll;
    				if(val(a,b,ll)==val(f[v].a,f[v].b,ll)){
    					ll=nr;
    					while(ll<r&&val(a,b,ll)==val(f[v].a,f[v].b,ll)) ++ll;
    				}
    				if(val(a,b,ll)>val(f[v].a,f[v].b,ll)) flag=1;
    			}else if(val(a,b,ll)<val(f[v].a,f[v].b,ll)) flag=1;
    			if(flag){
    				// two side
    				int nl1,nr1;
    				nl1=l,nr1=nl-1;
    				int mid=((l+r)%2!=0)?(l+r-1)/2:(l+r)/2;
    				if(nr1<=mid) add(v*2,l,mid,a,b,nl1,nr1);
    				else if(nl1>mid) add(v*2+1,mid+1,r,a,b,nl1,nr1);
    				else{
    					add(v*2,l,mid,a,b,nl1,mid);
    					add(v*2+1,mid+1,r,a,b,mid+1,nr1);	
    				}
    				nl1=nr+1,nr1=r;
    				mid=((l+r)%2!=0)?(l+r-1)/2:(l+r)/2;
    				if(nr1<=mid) add(v*2,l,mid,a,b,nl1,nr1);
    				else if(nl1>mid) add(v*2+1,mid+1,r,a,b,nl1,nr1);
    				else{
    					add(v*2,l,mid,a,b,nl1,mid);
    					add(v*2+1,mid+1,r,a,b,mid+1,nr1);	
    				}
    			}else{
    				//one side
    				int mid=((l+r)%2!=0)?(l+r-1)/2:(l+r)/2;
    				if(nr<=mid) add(v*2,l,mid,a,b,nl,nr);
    				else if(nl>mid) add(v*2+1,mid+1,r,a,b,nl,nr);
    				else{
    					add(v*2,l,mid,a,b,nl,mid);
    					add(v*2+1,mid+1,r,a,b,mid+1,nr);	
    				}
    			}
    		}
    	}
    	if(l==r) return;
    }
    
    LL query(LL v,LL l,LL r,LL x,LL s){
    	if(f[v].a>XXX)s=max(s,val(f[v].a,f[v].b,x));
    	if(l==r) return s;
    	int mid=((l+r)%2!=0)?(l+r-1)/2:(l+r)/2;
    	if(x<=mid) return query(v*2,l,mid,x,s);
    	else return query(v*2+1,mid+1,r,x,s);
    }
    
    int main(){
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    	N=read();
    	Q=read();
    	LL i,j;
    	
    	for (i=1;i<=N;++i)
    		a[i]=read(),b[i]=read();
    	memset(f,128,sizeof(f));
    	minx=1e18;
    	maxx=-1e18;
    	for (i=1;i<=Q;++i){
    		x[i]=read();
    		minx=min(x[i],minx);
    		maxx=max(x[i],maxx);
    	}
    	
    	for (i=1;i<=N;++i)
    		add(1,minx,maxx,a[i],b[i],minx,maxx);
    	
    	for (i=1;i<=Q;++i)
    		printf("%lld
    ",query(1,minx,maxx,x[i],-1e18));
    }
    
  • 相关阅读:
    js之自定义鼠标右键菜单
    js之键盘控制div移动
    js之select标签---省市联动小例子
    html之浮动和定位
    java开发简单的用户管理系统
    ASP.NET Web API 2中的属性路由(Attribute Routing)
    ASP.NET Web API中的路由
    Web API 2中的操作结果
    WebApi~通过HttpClient来调用Web Api接口
    Quartz.NET 作业调度
  • 原文地址:https://www.cnblogs.com/Chandery/p/11468241.html
Copyright © 2020-2023  润新知