ZJOI2018 歷史 結論 LCT思想

2021-10-06 23:53:10 字數 3540 閱讀 1329

題意:一棵n

nn個點的樹,每個點有權值a

ia_i

ai​,初始時給定。維護:

單點權值加上乙個正數。

詢問每個點恰好執行a

ia_i

ai​次 access 操作,任意安排順序的條件下切換輕重鏈總次數的最大值。

n ≤4

×105

n\leq 4\times 10^5

n≤4×10

5一道奇怪的題(?)

對於乙個點u

uu,考慮它子樹內兩個相鄰 access的點,它們在u

uu這裡切換了一次當且僅當它們屬於 不同的 u

uu的兒子 為根 的 子樹。(為了方便,我們把u

uu單獨這乙個點看成u

uu的子樹。)

把來自同乙個子樹內的一次access看成一種顏色的小球,我們希望相鄰的不同色小球盡量多。

結論設總小球數為n

nn,顏色最多的小球個數為m

mm,那麼最大貢獻為min

⁡\min\

min

證明

考慮把最多的顏色擺出來,在m−1

m-1m−

1個空隙中放其他顏色。

假設最多的顏色只有一種

把所有其他顏色的球依次往空隙中放,放完乙個顏色繼續往下乙個空隙放,空隙放完了再從第乙個開始。

如果空隙都放完了,即n−m

≥m−1

n-m\geq m-1

n−m≥m−

1,即n−1

≤2(n

−m

)n-1\leq2(n-m)

n−1≤2(

n−m)

,所有相鄰的小球顏色都不同,答案為n−1

n-1n−

1 否則顏色最多的球一定會相鄰。考慮開始時貢獻為0

00,插入乙個任意顏色的球最多讓貢獻+2+2

+2,上面的構造方法可以達到這個最大值,所以最大貢獻為2(n

−m

)2(n-m)

2(n−m)

最多的顏色有多種

顯然這時m≤n

2m\leq \frac

m≤2n

​,把最多的顏色各取乙個構成一組綁在一起,然後其他顏色用同樣的方法放在組之間的空隙內,這樣不會有同色相鄰。

就可以o(n

)o(n)

o(n)

處理了然後考慮怎麼用資料結構維護這玩意

上面已經推過了,雖然表示式看起來很奇怪,但實際上本質上是判斷最大的子樹是否超過自己的一半(這裡的大小都是指a

aa的和)

一點也不自然地想到實鏈剖分

具體而言,設sum

usum_u

sumu

​表示u

uu子樹內權值和,對於u

uu和它的兒子v

vv,如果2su

mv

>su

mu+1

2sum_v>sum_u+1

2sumv​

>su

mu​+

1(先不管u

uu本身什麼的),那麼v

vv是u

uu的重兒子,顯然重兒子最多有乙個。如果不存在這樣的兒子就沒有重兒子。

這樣做的好處是重鏈上都是取的min

⁡\min\

min的右邊這項,而把父親和兒子加上同乙個正數時左邊會變大,右邊不會變,而右邊本來就比左邊小,不僅仍然是重邊,連這個點的答案都不會改變,直接跳過去就可以了。而到根的輕邊是o

(log⁡v

)o(\log v)

o(lo**

)的,直接討論一下輕邊的情況即可。

具體而言就是魔改一下lct的access,跳輕邊的時候需要判一下。具體實現的時候很詭異,建議直接看**。

注意複雜度是通過輕邊條數而非finger-search保證的,所以必須在修改前dfs一遍處理出重兒子

複雜度應該是o(n

log⁡

nlog⁡v

)o(n\log n\log v)

o(nlog

nlo**)

#include

#include

#include

#include

#include

#define maxn 400005

using

namespace std;

typedef

long

long ll;

inline

intread()

int ch[maxn][2

],fa[maxn]

;ll val[maxn]

,lz[maxn]

;inline

void

pushlzy

(int x,ll v)

inline

void

pushdown

(int x)

}inline

intget

(int x)

inline

bool

isroot

(int x)

inline

void

rotate

(int x)

int q[maxn]

,tp;

inline

void

splay

(int x)

rotate

(x);}}

ll res[maxn]

,a[maxn]

,ans;

inline

intfindrt

(int x)

inline

void

access

(int x,

int v)

}vector<

int> e[maxn]

;void

dfs(

int u)

for(

int i=

0;i<

(int

)e[u]

.size()

;i++)if

(e[u]

[i]!=fa[u]&&2

*val[e[u]

[i]]

>val[u]+1

) ch[u][1

]=e[u]

[i];

res[u]

=(ch[u][1

]?2*

(val[u]

-val[ch[u][1

]]):val[u]-1

);if(

2*a[u]

>val[u]+1

) res[u]=2

*(val[u]

-a[u]);

ans+

=res[u];}

intmain()

dfs(1)

;printf

("%lld\n"

,ans)

;while

(m--

)return0;

}

ZJOI2018遊記總結

題解在此,雖然我並沒有看懂 其實省選三天前就結束了,但因為這兩天忙於補作業,並且我覺得這次省選比較有借鑑意義,所以我放到今天才寫。時間回到考試當天,那天早上六點多我們就除了賓館,匆匆填飽了肚子便奔赴考場。題目發下來,t1我看了一眼就感覺是數學題 我數學不好 於是先放下了t1。t2明顯是有暴力分的,所...

ZJOI2018二試遊記

zjoi2018果然比hnoi2018 本菜雞騙了200,分數上肯定比zjoi多 良心多了,一試和二試都是,每次都有幾天聽課。重點是 zjoi有飯吃!上午從學校出發,坐了4個小時來到yy,中午自己解決,晚飯在yyzx的食堂吃了幾個月來最 的飯菜 綠豆湯裡有生的綠豆?想到明天要聽課,於是晚上逛了逛知乎...

餘姚中學ZJOI2018遊記 4 25

今天是集訓的第二天,也是最後一天。早上講了一些國家集訓隊互測的題。我看到ppt的名字 一些毒瘤互測題的解法 就覺得特別的難,果然也是特別的難。有很多數論的不可做題。自己還是太菜了,對於數論的東西基本上沒有了解,什麼莫比烏斯反演,ntt雖然聽過,但我都不會,於是講課的時候聽到這些演算法就 啊哦,聽過 ...