傳送門
sol
70pts的很好做,暴力預處理之後直接回答即可,複雜度o(n
2)
o(n^2)
o(n2
)100pts的其實只需要加乙個倍增(和乙個set/雙向鍊錶)
先說說預處理,
設n xt
[i][
0]
nxt[i][0]
nxt[i]
[0],dis
[i][
0]
dis[i][0]
dis[i]
[0]表示從i
ii出發到最近的點及到這個點的距離
設n xt
[i][
1]
nxt[i][1]
nxt[i]
[1],dis
[i][
1]
dis[i][1]
dis[i]
[1]表示從i
ii出發到次近的點及到這個點的距離
乙個set把元素按高度排序之後順次扔進去,由於set元素有序,直接嘗試對前後最近、次近的元素進行修改即可,複雜度o(n
∗log
n)
o(n*logn)
o(n∗lo
gn)據說雙向鍊錶也可以實現,然而wtcl不會(
預處理完之後,就可以倍增實現答案的回答
設p os
[i][
j]
pos[i][j]
pos[i]
[j]表示從i
ii開始走了2
j2^j
2j輪之後所到的的位置,並設f[i
][j]
[0]、
f[i]
[j][
1]
f[i][j][0]、f[i][j][1]
f[i][j
][0]
、f[i
][j]
[1]分別表示兩車已行駛的距離
然後就是正常的倍增操作了
注意初始化
**:
#include
using
namespace std;
#define re register
#define ll long long
inline
intrd()
const
int n=
1e5+5;
struct pta[n]
;inline
bool
operator
<
(pt a,pt b)
sets;set
::iterator it;
int n,m,x0,s0,nxt[n][2
],dis[n][2
],pos[n][20
];ll f[n][20
][2]
;inline
void
edit
(pt x,pt y)
inline
void
query
(int s,
int x,ll &disa,ll &disb)
signed
main()
if((++it)
!=s.
end())
}for
(int re i=
1;i<=n;
++i)pos[i][0
]=nxt[nxt[i][1
]][0
],f[i][0
][0]
=dis[i][1
],f[i][0
][1]
=dis[nxt[i][1
]][0
];for(
int re j=
1;j^20;
++j)
for(
int re i=
1;i<=n;
++i)
pos[i]
[j]=pos[pos[i]
[j-1]]
[j-1
],f[i]
[j][0]
=f[i]
[j-1][
0]+f[pos[i]
[j-1]]
[j-1][
0],f[i]
[j][1]
=f[i]
[j-1][
1]+f[pos[i]
[j-1]]
[j-1][
1]; x0=rd(
);ll re a=
1e15
,b=0ll
;for
(int re i=
1;i<=n;
++i)
printf
("%d\n"
,s0)
; m=rd(
);while
(m--
)}
NOIp2012 開車旅行
傳送門 以後序列上的問題可以想一想倍增。s a i s b i sa i sb i sa i sb i 記錄在i ii這個位置讓a b a ba b開車到達的點。把a aa和b bb都跳一次稱為一輪。d is i j dis i j dis i j 表示從i ii跳2 j2 j 2j輪的總路程。p ...
luogu p1081 開車旅行
傳送門 此題為複雜細節題,無法總結題意,所以給出原題 小 text 和小 text 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 h i 城市 i 和城市 j 之間的距離 d 恰好是這兩個...
Noip2012 開車旅行
小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj 旅行過程中...