zoukankan      html  css  js  c++  java
  • 【YbtOJ#482】爬上山顶

    题目

    题目链接:https://www.ybtoj.com.cn/contest/116/problem/2

    (nleq 5 imes 10^5,x,yleq 10^6)

    思路

    考虑求出点 (i) 左右分别能看到的最高点,然后在两者之间取最大值。
    以左边为例,可以发现肯能造成贡献的一定位于上凸壳上,然后点 (i) 被贡献到的其实就是我们把点 (i) 插入到单调栈并维护好之后,单调栈中栈顶第二个元素。
    求好了点 (i) 能看到的最高点 ( ext{nxt}_i),接下来求点 (i) 到山顶的步数。
    我们把点按照 ( ext{nxt}_i) 的高度从大到小排序(高度相同右边在前),然后依次插入 set 中,每次插入前在 set 中找到这个点 (x) 前进方向上遇到的第一个点 (y),那么 (x) 在走到 (y) 之后就会向 ( ext{nxt}_y) 走。那么显然 (ans_x=ans_y+|x-y|)。其实类似一个拓扑排序的过程。
    时间复杂度 (O(nlog n))

    代码

    #include <bits/stdc++.h>
    #define reg register
    using namespace std;
    typedef long long ll;
    
    const int N=500010,Inf=1e9;
    int n,rt,top,X[N],Y[N],st[N],nxt[N];
    ll ans[N];
    
    int read()
    {
    	int d=0; char ch=getchar();
    	while (!isdigit(ch)) ch=getchar();
    	while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    	return d;
    }
    
    void write(ll x)
    {
    	if (x>9) write(x/10);
    	putchar(x%10+48);
    }
    
    struct node
    {
    	int id,nxt;
    }b[N];
    
    bool cmp(node x,node y)
    {
    	return (Y[x.nxt]==Y[y.nxt])?(x.nxt<y.nxt):(Y[x.nxt]>Y[y.nxt]);
    }
    
    double slope(int i,int j)
    {
    	return 1.0*(Y[j]-Y[i])/(X[j]-X[i]);
    }
    
    void solve()
    {
    	for (;top;top--) st[top]=0;
    	for (reg int i=1;i<=n;i++)
    	{
    		while (top>1 && slope(st[top],st[top-1])<slope(st[top],i))
    			st[top]=0,top--;
    		st[++top]=i;
    		int j=st[top-1];
    		if (Y[j]>=Y[nxt[i]]) nxt[i]=j;
    	}
    }
    
    void flip()
    {
    	for (reg int i=1;i<=n/2;i++)
    	{
    		swap(X[i],X[n-i+1]); swap(Y[i],Y[n-i+1]);
    		swap(nxt[i],nxt[n-i+1]);
    	}
    	for (reg int i=1;i<=n;i++)
    	{
    		if (nxt[i]) nxt[i]=n-nxt[i]+1;
    		X[i]=n-X[i]+1;
    	}
    	rt=n-rt+1;
    }
    
    void dp()
    {
    	for (reg int i=1;i<=n;i++)
    		b[i]=(node){i,nxt[i]};
    	sort(b+1,b+1+n,cmp);
    	set<int> s;
    	s.insert(0); s.insert(Inf);
    	for (reg int i=1;i<=n;i++)
    	{
    		int j=b[i].id,k=b[i].nxt;
    		if (j==rt) continue;
    		if (k<j)
    		{
    			int p=*(--s.lower_bound(j));
    			if (p<=k) ans[j]=ans[k]+j-k;
    				else ans[j]=ans[p]+j-p;
    		}
    		else
    		{
    			int p=*s.upper_bound(b[i].id);
    			if (p>=k) ans[j]=ans[k]+k-j;
    				else ans[j]=ans[p]+p-j;
    		}
    		s.insert(j);
    	}
    }
    
    int main()
    {
    	freopen("mountain.in","r",stdin);
    	freopen("mountain.out","w",stdout);
    	n=read();
    	for (reg int i=1;i<=n;i++)
    	{
    		X[i]=read(); Y[i]=read();
    		if (Y[i]>=Y[rt]) rt=i;
    	}
    	solve(); flip(); solve(); dp();
    	for (reg int i=n;i>=1;i--)
    		write(ans[i]),putchar(10);
    	return 0;
    }
    
  • 相关阅读:
    Django ORM操作
    django路由系统
    django(模版)
    mysql(函数,存储过程,事务,索引)
    mysql(单表查询,多表查询,MySQl创建用户和授权,可视化工具Navicat的使用)
    pycharm基本用法
    JS在浏览器中输出各种三角形
    异常处理,内置方法(__new__,__init__,__del__析构方法,单例模式,item系列)
    反射,内置方法,__str__ __repr__
    C. Swap Letters 01字符串最少交换几次相等
  • 原文地址:https://www.cnblogs.com/stoorz/p/14409099.html
Copyright © 2011-2022 走看看