繼紫荊花之戀後第二道蒟蒻所知道的會動的樹的點分治
題意:給你一顆未知的樹,你只知道1,你可以詢問explore(u,v),得到(u,v)路徑上的第乙個點,請你在有限的詢問次數內確定這一棵樹
首先隨機化一下訪問次數,這樣就不會被奇奇怪怪地卡掉了(雖然出題人也是隨的資料)
①:鏈,詢問次數限制n+logn,記錄鏈的兩端,一端不對跳到另一端,期望出錯次數logn
②:樹,詢問次數限制nlogn
我們可以每次跳到explore得到的點所屬的下一層重心,這樣每次少去一半的點,就可以保證詢問次數是nlogn了
所以現在考慮的就是怎麼維護動態的重心,所以大概按照紫荊花之戀的做法就ok
o k了
但其實有兩種寫法,
第一種就是每次找到乙個新的點就看看樹是否平衡(這樣就和紫荊花之戀一模一樣了)
第二種就是把那條未訪問的鏈一次性走到底,然後再去重構點分樹
這裡說一下第二種做法
後面一直在考慮,怎麼維護這個點所屬的下一層重心??
參考了別人的**後發現可以用ma
p map
存一下g[
u][v
] g[u
][v]
,表示u u
所屬的重心走到
v' role="presentation" style="position: relative;">v
v後所屬的下一層重心
然後我想到重構的時候怎麼去dfs清空這棵樹?
然後發現可以用au
to. aut
o.
…..c+
+11c ++
11真是神奇,這樣的話就是最後拉一條鏈出來後再chk就好了
然後實際上第二種要快得多(其實想想也知道)
#include
#include"rts.h"
#define fp(i,a,b) for(int i=a,i=b+1;i#define fd(i,a,b) for(int i=a,i=b-1;i>i;--i)
#define go(i,u) for(int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define get explore
#define pb push_back
using
namespace
std;
template
inline
bool cmax(t&a,const t&b)
template
inline
bool cmin(t&a,const t&b)
const
int n=3e5+5;
const
double alpha=0.777;
typedef
int arr[n];
struct ege[n<<1];
int n,ce,rt,rt,sum;arr sz,fx,fa,fr,fi,dsz;bool vis[n];
vector
id,new,s;
mapg[n];
inline
void add(int u,int v),fi[u]=ce;}
inline
void adc(int fa,int rt,int in)
void gr(int u,int fa)
void clr(int u)
inline
void re(int u)
inline
void find(int x)
for(int i:s)dsz[fa[i]]-=dsz[i];for(int i:new)dsz[i]=1;
for_each(s.rbegin(),s.rend(),(int i));
for(int i:s)if(dsz[i]>dsz[fa[i]]*alpha)return re(fa[i]);
}inline
void chain()
}void play(int _,int,int ty)
WC2018即時戰略
題目描述 小 m 在玩乙個即時戰略 real time strategy 遊戲。不同於大多數同類遊戲,這個遊戲的地圖是樹形的。也就是說,地圖可以用乙個由 n 個結點,n 1 條邊構成的連通圖來表示。這些結點被編號為 1 sim n 每個結點有兩種可能的狀態 已知的 或 未知的 遊戲開始時,只有 1 ...
UOJ 349 WC2018 即時戰略
題目鏈結 一開始已知一號點。每次可以選定乙個已知點和乙個未知點,然後互動庫會返回從已知點出發到達未知點路徑上的第二個點。要求在有限步之內知道每乙個點。次數要求 鏈的情況要求 o n o n o n 其餘是 o n logn o nlogn o nlog n 首先是鏈的情況,記錄當前左右端點不斷往後探...
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 ...