• Mountainous landscape


    Portal --> broken qwq

    Solution

    ​  所以我不是很懂为什么我场上想到了凸包的解法但是。。老想着。。要整体处理==有毒

    ​  一开始。。自己进入了一个误区就是老想着要求交点

    ​​  但是很显然求交点你就凉了,所以我们要转化问题Mountainous_Landscape

    ​​  我们把橙黄色的那条线画出来,然后就发现。。其实我们是可以很方便地判断一段线段((P_3P_4)),在某一个区间里面有没有解,具体的话就是。。我们维护这个区间的上凸包,然后判断一下这条线跟是否与这个上凸包相交就好了

    ​​  那然后就直接。。线段树维护每个区间的上凸包。。然后直接在线段树上查答案就ok了然后记得优先左儿子。。时间复杂度(O(nlog^2n))

    ​  

    ​  代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int N=1e5+10,SEG=N*4;
    const double eps=1e-6;
    struct Dot{
    	double x,y;
    	Dot(){}
    	Dot(double _x,double _y){x=_x; y=_y;}
    }a[N];
    bool slope_dec(int x,int y,int i){return (a[x].y-a[y].y)*(a[y].x-a[i].x)>(a[y].y-a[i].y)*(a[x].x-a[y].x);}
    void line(int x,int y,double &k,double &b){
    	k=(a[x].y-a[y].y)/(a[x].x-a[y].x);
    	b=a[x].y-k*a[x].x;
    }
    bool k_bigger(int x,int y,double k){
    	if (a[y].x>a[x].x) swap(x,y);
    	return (a[x].y-a[y].y)>k*(a[x].x-a[y].x);
    }
    int n,ans;
    namespace Seg{/*{{{*/
    	int ch[SEG][2],top[SEG];
    	vector<int> rec[SEG];
    	int n,tot;
    	double k,b;
    	void _build(int x,int l,int r){
    		rec[x].resize(r-l+3); top[x]=0;
    		for (int i=l;i<=r+1;++i){
    			while (top[x]>1&&!slope_dec(rec[x][top[x]-1],rec[x][top[x]],i)) --top[x];
    			rec[x][++top[x]]=i;
    		}
    		rec[x].resize(top[x]+1);
    		if (l==r) return;
    		int mid=l+r>>1;
    		ch[x][0]=++tot; _build(ch[x][0],l,mid);
    		ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
    	}
    	void build(int _n){n=_n; tot=1; _build(1,1,n);}
    	int check(int x){
    		int l=1,r=top[x]-1,mid,tmp1,tmp2,ans=r;
    		while (l<=r){
    			mid=l+r>>1;
    			tmp1=rec[x][mid];
    			tmp2=rec[x][mid+1];
    			if (k_bigger(tmp1,tmp2,k)) 
    				ans=mid,l=mid+1;
    			else r=mid-1;
    		}
    		tmp1=rec[x][ans+1];
    		if (k*a[tmp1].x+b+eps<=a[tmp1].y) return tmp1-1;
    		else return 0;
    	}
    	int _query(int x,int l,int r,int lx,int rx){
    		int mid=lx+rx>>1,tmp;
    		if (l<=lx&&rx<=r){
    			if (lx==rx) return check(x);
    			if (!check(x)) return 0;
    			if (check(ch[x][0]))
    				return _query(ch[x][0],l,r,lx,mid);
    			return _query(ch[x][1],l,r,mid+1,rx);
    		}
    		if (r<=mid)
    			return _query(ch[x][0],l,r,lx,mid);
    		else if (l>mid)
    			return _query(ch[x][1],l,r,mid+1,rx);
    		else{
    			tmp=_query(ch[x][0],l,mid,lx,mid);
    			if (tmp) return tmp;
    			return _query(ch[x][1],mid+1,r,mid+1,rx);
    		}
    	}
    	int query(int l,int r,double k1,double b1){k=k1; b=b1;return _query(1,l,r,1,n);}
    	void _debug(int x,int lx,int rx){
    		printf("#%d %d: ",lx,rx);
    		for (int i=1;i<=top[x];++i) printf("%d ",rec[x][i]);
    		printf("
    ");
    		if (lx==rx)  return;
    		int mid=lx+rx>>1;
    		_debug(ch[x][0],lx,mid);
    		_debug(ch[x][1],mid+1,rx);
    	}
    	void debug(){_debug(1,1,n);}
    }/*}}}*/
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	double k,b;
    	scanf("%d",&n);
    	for (int i=1;i<=n;++i)
    		scanf("%lf%lf
    ",&a[i].x,&a[i].y);
    	Seg::build(n-1);
    	//Seg::debug();
    	for (int i=1;i<n;++i){
    		ans=0;
    		if (i<=n-2){
    			line(i,i+1,k,b);
    			ans=Seg::query(i+1,n-1,k,b);
    		}
    		printf("%d ",ans);
    		//Seg::debug();printf("
    ");
    	}
    }
    
  • 相关阅读:
    4. Git撤销修改
    3. Git如何管理修改
    2. Git的工作区、暂存区和版本库
    1. Git创建仓库、查看工作区状态
    微信平台接入Web页面功能接口(C#)
    Python之路【第六篇】:Python运算符
    Python之路【第五篇】:Python基本数据类型
    Python之路【第四篇】:Pycharm集成开发环境
    Python之路【第二篇】:Python简介、解释器与编码
    Python之路【第七篇】:Python流程控制
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9552444.html
Copyright © 2020-2023  润新知