Noip 2012 開車旅行 倍增DP

2021-08-09 04:58:58 字數 3167 閱讀 7349

我們先用set預處理出,在每乙個城市,a和b下一次分別要去的地方

那麼是求對於距離每個城市最小的和次小距離的其他城市。

由於set的自動有序性,我們可以先找到位於城市的指標,然後找這個指標左邊的兩個,右邊的兩個,最小和次小距離一定在這四個數之中。

然後乙個乙個點模擬會t掉。。。我們可以設小a,小b各開一次車為一輪,f(

i,j)

f (i

,j

)表示在第i個城市,開2j

2

j車會到的城市,da

(i,j

) da(

i,j)

表示小a從第i個城市開始,經歷了2j

2

j輪,小a開車的距離,db

(i,j

) db(

i,j)

同理倍增的核心思想是2i

−1+2

i−1=

2i2 i−

1+2i

−1=2

i所以可得狀態轉移方程: f(

i,j)

=f(f

(i,j

−1),

j−1)

f (i

,j)=

f(f(

i,j−

1),j

−1

)da(

i,j)

=da(

i,j−

1)+d

a(f(

i,j−

1),j

−1) da(

i,j)

=da(

i,j−

1)+d

a(f(

i,j−

1),j

−1

)db(

i,j)

=db(

i,j−

1)+d

b(f(

i,j−

1),j

−1) db(

i,j)

=db(

i,j−

1)+d

b(f(

i,j−

1),j

−1

)da和db的方程是這樣推出來的:由於那個核心思想,我們想要從i走2j

2

j步,就可以先走2j

−12 j−

1步,再走2j

−12 j−

1步,因此就有了 da

(i,j

−1)+

da(f

(i,j

−1),

j−1)

d a(

i,j−

1)+d

a(f(

i,j−

1),j

−1

)。其中f(

i,j−

1)f (i

,j−1

)表示從i走2j

−12 j−

1步會到達的城市。

關於倍增的預處理**:

for(int i=1; i

<=n; i++)

if(f2!=0)

f[i]

[0] = f2;

}for(int j=1; j

<=16; j++)

for(int i=1; i

<=n; i++)

}

另外…set的find操作有點慢,但set自帶乙個lower_bound(),速度大體上快於find

#include 

#include

#include

#include

#include

#include

using

namespace

std;

#define debug(x) cerr<<#x<<"="int maxn = 100010, maxm = 10010;

const

int inf =0x7fffffff - 10;

int x0,xi,si,n,m,h[maxn],sta[maxn],stb[maxn],cnt;

int fa[maxn], fb[maxn],dda[maxn],ddb[maxn];

int f[maxn][20],da[maxn][20],db[maxn][20];

struct city

}c[maxn];

struct temp

}tem[6];

set s;

set :: iterator it;

void init() ;

if(it!=s.begin()) ;

it++;

}it++;

}if((++it)!=s.end()) ;

if((++it)!=s.end()) ;}}

sort(tem+1,tem+cnt+1);

if(tem[1].id)

if(tem[2].id)

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

if(f2!=0)

f[i][0] = f2;

}for(int j=1; j<=16; j++) }}

}double work1(int s, int x)

}if(fa[s]&&da[s][0]<=x)

if(xb == 0) return (double)inf;

return

double(xa)/double(xb);

}void work2(int s, int x)

}if(fa[s]&&da[s][0]<=x)

printf("%lld %lld\n", xa,xb);

}int main()

init();

scanf("%d", &x0);

double ans1 = inf+1,tem_ans;

int ansid;

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

}printf("%d\n",ansid);

scanf("%d", &m);

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

return

0;}

NOIP2012 開車旅行 (倍增)

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

NOIP2012開車旅行 倍增

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

noip2012 開車旅行 set 倍增

因為要快速查詢向後跳應該是哪乙個點,所以用set,迭代器左右晃一下查詢最接近的兩個元素 p選手是不是只能用平衡樹 然後用倍增記錄i節點跳2 j步後,a和b分別走的距離。具體的細節和統計答案也需要注意。include include include include include include de...