日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JZOJ 3401 JZOJ 5673. 【GDOI2018Day1模拟4.20】爬山法

發(fā)布時(shí)間:2025/3/15 编程问答 13 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JZOJ 3401 JZOJ 5673. 【GDOI2018Day1模拟4.20】爬山法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Description

Input

輸入文件的第一行含有一個(gè)正整數(shù) n,代表山的頂點(diǎn)數(shù)。
接下來 n 行,每行包含兩個(gè)整數(shù) x i 和 y i ,代表一個(gè)頂點(diǎn)的坐標(biāo)。輸入保證 x i單調(diào)遞增。

Output

輸出 n 行,第 i 行包含一個(gè)整數(shù),代表從第 i 個(gè)頂點(diǎn)出發(fā)走到最高點(diǎn)需要經(jīng)過多少段。

Sample Input

5
1 5
2 4
3 9
4 0
5 2

Sample Output

2
1
0
1
2

Data Constraint

Hint

Solution

  • 我們?cè)O(shè) l[i]?(r[i]) 表示點(diǎn) i 向左(右)看能看到的點(diǎn)最高是哪一個(gè)。

  • 這用單調(diào)棧可以 O(N) 求出來——左右掃一遍就可以了。

  • 之后我們發(fā)現(xiàn)最難統(tǒng)計(jì)的就是一個(gè)點(diǎn)不斷發(fā)現(xiàn)新的高點(diǎn),從而一直拐彎。

  • 那么我們又設(shè) fl[i]?(fr[i]) 表示點(diǎn) i 向左(右)第一個(gè)能看到更高點(diǎn)的位置。

  • 這我們也可以近乎 O(N) 求出來,一樣是掃一遍,用前面的 fl[] 更新當(dāng)前的 fl[i]

  • 那么點(diǎn) i 能看到的最高高度就是 f[i]=max(fl[i],fr[i]) ,走的方向也就確定了。

  • 之后我們以最高點(diǎn)為 root ,連邊 (fl[i],i) (或 fr[i] ,以走的方向而定)。

  • 顯然這是一個(gè)樹結(jié)構(gòu),因?yàn)槊總€(gè)點(diǎn)始終會(huì)到最高點(diǎn)(一定連通),目標(biāo)點(diǎn)又越來越高(沒環(huán))。

  • 于是跑一邊 dfs ,就能算出每個(gè)點(diǎn)走的段數(shù)了。

  • 時(shí)間復(fù)雜度近乎 O(N)

Code

#include<cstdio> #include<cctype> using namespace std; const int N=2e5+5; struct data {int x;long long y; }a[N]; int top,tot,root; int first[N],nex[N],en[N]; int l[N],r[N],st[N],ans[N],fl[N],fr[N],fx[N]; long long f[N]; double d[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) w|=ch=='-',ch=getchar();while(isdigit(ch)) X=(X<<1)+(X<<3)+(ch^48),ch=getchar();return w?-X:X; } inline void write(int x) {if(x>9) write(x/10);putchar(x%10+'0'); } inline double get(int x,int y) {return (a[x].y-a[y].y)*1.0/(a[x].x-a[y].x); } inline int abs(int x) {return x<0?-x:x; } void dfs(int x) {for(int i=first[x];i;i=nex[i]){ans[en[i]]=ans[x]+abs(x-en[i]);dfs(en[i]);} } inline void insert(int x,int y) {nex[++tot]=first[x];first[x]=tot;en[tot]=y; } int main() {int n=read();for(int i=1;i<=n;i++) a[i].x=read(),a[i].y=read();for(int i=1;i<=n;i++){while(top>1 && d[top]<=get(i,st[top])) top--;if(a[st[top]].y>a[i].y) l[i]=st[top];st[++top]=i;if(top>1) d[top]=get(i,st[top-1]);}top=0;for(int i=n;i;i--){while(top>1 && d[top]>=get(i,st[top])) top--;if(a[st[top]].y>=a[i].y) r[i]=st[top]; else r[i]=n+1;st[++top]=i;if(top>1) d[top]=get(i,st[top-1]);}r[n]=n+1;for(int i=1;i<=n;i++) a[i].y=a[i].y*1000000+i;for(int i=1;i<=n;i++){long long h=a[i].y;if(a[r[i]].y>h) h=a[r[i]].y,fx[i]=2;if(a[l[i]].y>h) h=a[l[i]].y,fx[i]=1;f[i]=h;}for(int i=1;i<=n;i++){int j=i-1;while(j && f[i]>=f[j]) j=fl[j];fl[i]=j?j:l[i];}for(int i=n;i;i--){int j=i+1;while(j<=n && f[i]>=f[j]) j=fr[j];fr[i]=j<=n?j:r[i];}for(int i=1;i<=n;i++)if(!fx[i]) root=i; elseif(fx[i]==1) insert(fl[i],i); else insert(fr[i],i);dfs(root);for(int i=1;i<=n;i++) write(ans[i]),putchar('\n');return 0; }

總結(jié)

以上是生活随笔為你收集整理的JZOJ 3401 JZOJ 5673. 【GDOI2018Day1模拟4.20】爬山法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。