• 【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;
    }
    
  • 相关阅读:
    frame和iframe区别
    idea基本
    Spring中加载xml配置文件的六种方式
    java中Map,List与Set的区别
    java集合框架
    springmvc IDEA
    springmvc 精华
    eclipse 中 git 解决冲突(重点)
    启动Tomcat报错 java.util.zip.ZipException: invalid LOC header (bad signature)
    PowerDesigner 提示 Existence of index、key、reference错误
  • 原文地址:https://www.cnblogs.com/stoorz/p/14409099.html
Copyright © 2020-2023  润新知