標籤:分塊。
題解:200000,而且標號從0開始,很符合分塊的條件啊。看看怎麼實現。
首先分成√n個區間,然後如果我們對於每乙個位置i,求出乙個next[i]和step[i],分別表示跳到的後乙個位置與步數,因為是分塊所以就是跳到下乙個區間的步數與位置了。處理這兩個陣列要從前到後,只需要o(n)。
然後查詢:自然是使用這兩個陣列,跳出去就return,複雜度o(√n)。
修改:修改乙個點自然是o(1),但是前面的會跳到這個地方,那不是前面的都要改?非也,因為next僅僅跨越了乙個區間,所有最多有這個區間的起始位置到i個是需要更改的,也就是最大√n個,我們從i到起始位置煩著列舉,複雜度o(√n)。
所以總的複雜度為o(m√n)。
1 #include2 #include3 #include4 #include5using
namespace
std;
6const
int maxn=210000;7
intn,m,cnt;
8int
w[maxn],next[maxn],step[maxn],team[maxn];
9 inline int gi()
10void update(int
p)11
18int net=p+w[p];
19if(team[p]==team[net])
2024
else
2529}30
int query(int
p)31
38return
res;39}
40int
main()
4160
else
61 printf("
%d\n
",query(p));62}
63return0;
64 }
標籤:lct
題解:此題當然不缺乏lct做法,對於lct來說,這道題就是一道模板題,每次修改cut再link,維護sz代表子樹的大小。使用乙個根節點:n+1,也就是跳出去。m+a+s,查詢x的左子樹大小即可,也就是比他深度小的點的個數,不就是多少步跳出去嗎?
1 #include2 #include3 #include4using
namespace
std;
5const
int maxn=300099;6
intn,m;
7int fa[maxn],rev[maxn],val[maxn],q[maxn],ch[maxn][2
],sz[maxn];
8bool isroot(int x)
9void update(int x)
10bool
get(int x)
11void down(int x) }
12void rotate(int
x)13
20void splay(int
x)2130}
31void access(int x) }
32void makeroot(int x)
33void link(int x,int y)
34void cut(int x,int y)
35int
main( )
3650
else
5158}59
return0;
60 }
hnoi2010 彈飛綿羊
題目描述很明確,現在的目標是均攤兩個操作的複雜度 現在我們已知有兩種方法 1.每次用o 1 的時間修改k值,用o n 的時間直接模擬回答詢問 2.每次修改了k值後用o n 的時間更新所有答案,o 1 時間回答 均攤這兩種操作,可以這樣做 由於只可以從前往後跳,所以可以把跳躍路徑壓縮,更新時把壓縮的部...
HNOI 2010 彈飛綿羊
要求維護乙個 n 個節點的森林,實現 m個詢問,其中包括 n 200,000m 100,000 動態樹的入門題。只需要實現ac cess 操作以及維護子樹大小si ze即可。其實我做這道題是為了找找寫動態樹的感覺,發現了不少要注意的細節。總結地說,越是基本的函式就越不能打錯,不然就要花好多的時間去查...
HNOI2010彈飛綿羊
話說我是冒著巨大的風險a這道題的 xc說不讓上其他oj 這題其實很簡單,每個點如果他能往後跳,那就只能跳到唯一的乙個,這顯然是跟森林,用lct就好,維護下size。突然變短 include include define fo i,a,b for int i a i b i define lc c x...