倍增 luogu1081開車旅行

2021-08-21 20:36:50 字數 2858 閱讀 9707

傳送門

倍增神題????

細節超級多···

其實思路很簡單

對於每個點,a和b要開去的目的地是固定的,所以就想到了倍增

開三個倍增陣列,t[i][j][k]代表k從i開車走2^j天走到的那個城市

f是a走的路程,g是b走的路程

0代表a,1代表b

對於預處理,一開始怎麼想怎麼是n^2的

後來自己yy了一下覺得每次sort一下也行嘛!

look!就像這樣

sort(a+i+1,a+n+1,cmp);

int x=lower_bound(a+i+1,a+n+1,a[i])-a

;if(abs(a[x].h-a[i].h)>abs(a[x-1].h-a[i].h)) x--;

g[i][0][1]=abs(a[x].h-a[i].h); t[i][0][1]=x;

int y;

if(abs(a[x-1].h-a[i].h)<=abs(a[x+1].h-a[i].h)) y=x-1

;else y=x+1

;

外層i從n-1迴圈到1

但是我發現這樣子很容易會找到它自己,好像連樣例2都過不了

於是想到了排序+二分

我覺得這個其實也能過,但寫到一半放棄了覺得一定有更簡單的方法

這時候問了一下小夥伴他們看的是哪個題解(劃掉

然後學習到了一種高階操作(其實很簡單

那就是雙向鍊錶!

sort(a+1,a+n+1);//get到了雙向鍊錶**! 

for(int i=1;i<=n;i++) a[i].l=i-1,a[i].r=i+1,pos[a[i].id]=i;

a[1].l=a[n].r=0;

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

它可以很方便快捷地解決掉這種有限制性的排序問題

因為每次只能從小往大走,所以找完乙個小的就把它從鍊錶刪掉

這樣找後面的時候一定不會找到它

又因為事先排好了序,所以只要看左邊和右邊哪個更小就好啦!

是不是特別簡單!!!

好了,預處理解決完,就可以開始求倍增陣列了

和lca的套路十分相似,也是根據2次冪,但是要注意1的時候和》1的時候不一樣

所以要單獨考慮一下

求好了倍增陣列,這道題就做完了80%

然而我卻wa在了最後求答案的地方

因為倍增的題只做過lca···

所以十分*****地以為只要貪心地找到第乙個比x0小的就好了

啊我怎麼那麼傻啊喂,有可能還到不了x0啊

給你們看看我的傻**:

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

for(int j=17;j>=0;j--)

還有這個:

s=rd(); x

0=rd();

for(int i=17;i>=0;i--)

}

這錯誤思想簡直經典

其實正確寫法應該是這樣:

inline

void

solve(int

s,intx)}

看來基本上所有的倍增都是這麼乙個模板了0.0

說完這些整個題就已經出來了啊喂

這個看似複雜的題就被我們一步一步地解決掉了

其實所有很複雜的題都可以化成簡單的小問題解決的吧qvq

接下來看一下我的ac**!

#include

#include

#include

#include

#include

#define maxn 100005

#define ll long long

using namespace std;

int n,m,s,x

0,t[maxn][20][2],lg;//

0->a 1->b

intpos[maxn],aim,l,r,na[maxn],nb[maxn];

ll g[maxn][20][2],f[maxn][20][2],ans1,ans2,la,lb;//f->a g->b

inline int rd()

while(c<='9' && c>='0') x=x

*10+c-'0',c=getchar();

return

x*f;

}struct qw

qa[maxn];

inline bool cmp1(qwq x,qwq y)

inline bool quq()

inline int qvq(int x,int y)

inline void drive()

sort(a+1,a+n+1,cmp1);

for(int i=n-1;i;i--)

t[i][1][0]=t[y][0][1]; f[i][1][0]=f[i][0][0]; f[i][1][1]=f[x][0][0];

t[i][1][1]=t[x][0][0]; g[i][1][0]=g[y][0][1]; g[i][1][1]=g[i][0][1];

}for(int j=2;j<=lg;j++)

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

for(int k=0;k<=1;k++)

}inline void solve(int

s,intx)}

int main()

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

m=rd();

while(m--)

return

0;}

luogu1081 開車旅行

這個題目還是值得思考的.看到這個題目,大家應該都想到了這樣乙個思路,就是把每個點能夠達到的最近的和次近的點都預處理出來,然後跑就可以了,現在問題就是難在這個預處理上面,我們應該如何做呢?觀察到,近的概念是兩點之間的海拔距離最小,所以我們可以將海拔距離從後往前 畢竟你只能往你後面的地方走嘛.扔進乙個可...

Luogu1081 開車旅行

巨長的倍增題.顯然這是沒有什麼決策的,選擇方案都是固定的 這可以考慮倍增跳,每個位置上跳到的位置是可以通過查前驅後繼解決的 有兩種方式 一種是平衡樹搞法,倒著做查完了插入 另一種是先排序建乙個鍊錶,查完了刪除 都是可以通過加哨兵節點來搞的,結果我只想到了 set 亂搞,就寫了很長 預處理完就可做了 ...

P1081 開車旅行 倍增 (毒瘤題)

其實就是個大模擬。首先,根據題意,小a和小b從任意乙個城市開始走,無論 x 如何,其路徑是一定唯一的。顯然對於兩問都可以想出乙個 o n 2 的暴力,即直接一步一步地向右走。首先,我們當然需要知道a,b在每個城市的下一步如何走,記 nexta i nextb i 為a,b在 i 處時,下一步走到的城...