洛谷P1081 開車旅行 (Treap 倍增)

2021-08-08 21:40:00 字數 1856 閱讀 2802

題目傳送門:

題目分析:這題的兩個問其實是差不多的。第一問給出了x0,我們列舉起點s,就相當於變成了n個第二類詢問(s

,x0)

(1<=

s<=n)

。於是現在原問題變成了:給出(s,x),如何快速求s開始往下走不超過x距離時,a,b各走的距離?然後用資料結構預處理出a,b到達每乙個點之後會走哪個點,詢問時倍增往後跳統計答案即可。調**的時候注意a可能比b多走一步的情況,以及a,b走的距離均為0的情況。

code:

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn=100100;

const

int maxl=22;

const

long

long m1=998244353;

const

long

long m2=1000000007;

const

long

long m3=1333333331;

typedef

long

long ll;

struct tnode

tree[maxn];

tnode *root=null;

int cur=-1;

int next1[maxn];

int next2[maxn];

int next[maxn][maxl];

ll disa[maxn][maxl];

ll disb[maxn][maxl];

int a[maxn];

int n,m;

ll seed,x0;

ll suma,sumb;

int rand()

tnode *new_node(int v)

void right_turn(tnode *&p)

void left_turn(tnode *&p)

void insert(tnode *&p,int v)

else

}int get_prev(tnode *p,int x,int v)

int get_succ(tnode *p,int x,int v)

int abs(int x)

void work(int s,int x)

if ( next2[s] && abs(a[ next2[s] ]-a[s])<=left) suma+=abs(a[ next2[s] ]-a[s]);

}int main()

else

}//for (int i=1; i<=n; i++) printf("%d %d\n",next1[i],next2[i]);

for (int i=1; i<=n; i++)

}for (int j=1; jfor (int i=1; i<=n; i++)

}//for (int i=1; i<=n; i++) printf("%d\n",next[i][0]);

scanf("%lld",&x0);

int ans=0;

ll ansa=m1,ansb=-1;

for (int s=1; s<=n; s++)}}

printf("%d\n",ans);

scanf("%d",&m);

for (int i=1; i<=m; i++)

return

0;}

洛谷 P1081 開車旅行

題目描述 小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj ...

P1081 開車旅行

p1081 開車旅行 排序優化 倍增 其實這道題一開始是一點也沒有頭緒,知道有高人指點了一下。說並不需要拘束於出發點和路徑長度,也就是問題1.2。不過乙個是固定路徑長度的詢問,另乙個是給定起點和路徑長度的詢問。所以問題一和問題二是可以使用乙個函式解決的,而且對於乙個城市來說,在不考慮路程的情況下,路...

P1081 開車旅行

傳送門 用倍增的思想 設 a i 表示a在 i 位置走一步到達的城市以及經過的路程 這裡我用結構體存a i b同理 設 f i j 表示從 i 位置出發,走 2 j 輪後到達的城市 一輪即ab各走一次 dis i j 表示從 i 位置出發,走 2 j 輪後經過總路程 da i j 表示從 i 位置出...