題目鏈結
一開始已知一號點。
每次可以選定乙個已知點和乙個未知點,然後互動庫會返回從已知點出發到達未知點路徑上的第二個點。
要求在有限步之內知道每乙個點。
次數要求:
鏈的情況要求 o(n
)o(n)
o(n)
其餘是 o(n
logn
)o(nlogn)
o(nlog
n)首先是鏈的情況,記錄當前左右端點不斷往後探索即可。
然後是樹,初始想法肯定就是不斷迭代,最壞情況是 o(n
2)
o(n^2)
o(n2
) 的。
我們的瓶頸在於如果樹的深度比較大,我們迭代的時候來回走了很多個圈就不好處理。
那麼我們很容易想到用點分樹來優化我們迭代的過程。
於是動態維護點分樹即可。
每次新加乙個點的時候直接加入,向上更新點分樹祖先的 siz
esize
size
,設定乙個平衡因子,當當前子樹大小過大時就把當前子樹暴力重構一下。記錄每乙個點在點分樹中的深度就很好做了。
code:
#include
#include
"rts.h"
using
namespace std;
const
int n=
3e5+10;
namespace tp3}if
(rand()
&1)swap
(lnow,rnow);}
return;}
}namespace sola[n<<1]
;int head[n]
,cnt=0;
inline
void
add(
int x,
int y)
;head[x]
=cnt;
}int fa[n]
,vis[n]
,size[n]
,f[n]
,que[n]
,had[n]
,mark[n]
,sz[n]
,dep[n]
;int rt;
int now,sz,rt,up;
void
find
(int u,
int fr)
f[u]
=max
(f[u]
,sz-sz[u]);
if(!rt||
(f[u]
)) rt=u;
}void
build
(int u,
int fr)
return;}
void
clear
(int u,
int fa)
return;}
inline
void
rebuild
(int u)
void
maintain
(int u)
++size[fa[u]];
if(size[fa[u]
]*alpha) mark[fa[u]]=
1;maintain
(fa[u]);
if(mark[u]
)rebuild
(u);
// 找到最上面需要重構的點
return;}
void
work
(int _n)
else}}
}}void
play
(int n,
int t,
int datatype)
UOJ 349 WC2018 即時戰略
被cqz d沒了。我d cly 關你啥事 逃 首先鏈的情況直接rand就好了。期望次數 o n log n 然而我一開始寫掛了。開始扯淡 我用這個模數,就可以過原題資料 c l y a k i o i 但是用以下兩種都不行 g l y a k i o i c l y a k i o i n o i ...
uoj 349 WC2018 即時戰略
題目鏈結 正解 link cut tree 這道題我在考場上從看題到放棄只花了 20 多分鐘。爆剛 t2 無果,12 點的鐘聲響起,我無奈地開始看這道題,然後發現了生的希望。只寫了二十幾分鐘,然後又滾回去剛 t2 了。正解根本就沒去想了 雖然本來也不會。不得不說這道題的標算還是很妙的,我就算去想也不...
UOJ 349 WC2018 即時戰略
傳送門 按照紫荊花之戀的做法,動態維護一下點分樹的形態 把點隨機打亂 每次從當前的根開始 explore 如果已經有了就暴力跳到那個點 否則加入這個點 注意一條鏈的要單獨處理 include include rts.h using namespace std typedef long long ll...