BZOJ3052 糖果公園

2022-04-08 10:31:33 字數 4287 閱讀 6534

0、題目鏈結:

1、題目大意:給定一顆n個點的無根樹,每個點有乙個顏色,要進行q次操作,有兩種操作,顏色總數是m。

a) query操作,給定起始點和終點,對於這條路徑,從起始點出發,對於沿途的點,如果這個點的顏色j是第i次出現,那麼對於這個詢問的答案的貢獻是vi?wj。

b) change操作,每次修改乙個節點的顏色。

——截圖來自uoj

2、解題思路:

a)這道題在bzoj上的時間限制是200s,那麼對於前3個點,我們可以每次查詢在樹上dfs,修改直接改顏色。時間複雜度o(n2),期望得分30。

b)對於第四個和第五個點,我們發現m相對較小而且給出的是乙個鏈,還沒有修改操作,那麼我們可以將這個鏈看成乙個序列,並對這個序列進行分塊,每塊的大小是,考慮莫隊演算法,我們將需要查詢的區間排序,第一關鍵字按照左端點的塊,第二關鍵字我們按照右端點的編號排序,每次我們進行暴力的轉移,這樣,時間複雜度是o(n??√),為什麼呢?因為轉移分兩種,要麼都在這個n??√的塊中轉移,轉移n次,時間複雜度是o(n??√),要麼是這個塊中轉移到另外乙個塊,每次轉移是o(n),最多會有n??√次轉移,時間複雜度也是o(n??√),於是總體的時間複雜度是o(n??√)。

i.說了這麼多,也沒個**= =,莫隊演算法模板題:bzoj2038 小z的襪子

sort(q + 1, q + m + 1, cmp); //對詢問進行排序

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

while(r > q[i].r)

//實際上就是將r->q[i].r

while(l < q[i].l)

while(l > q[i].l)

//實際上就是將l->q[i].l

//計算這次詢問的答案

}加上a)演算法,期望得分50。

c)對於第六和第七個點,我們能看出和b)解法唯一區別就是給點的樹不是鏈了,那麼b)中的演算法能不能在這裡應用呢?序列能夠分塊,樹能不能分塊呢?如何分塊複雜度才能***呢?

i.我們先來看《手把手教你樹分塊系列》的bzoj1086 王室聯邦。這個題如何解決呢?我們先來陳述一下做法,我們用dfs去分塊,我們記錄乙個棧,當遍歷完某個節點的所有子樹後,我們將這個節點加入棧,每次遍歷完一棵子樹,以這個節點為祖先的棧裡的元素個數已經超過了我們規定的塊的大小b了,就把這些節點變成乙個塊,將這些元素從棧裡彈出,最後將棧中的殘留節點歸結到最後乙個塊中。

ii.那麼可以確定的是每棵子樹對這個節點的貢獻不過超過b,為什麼呢?因為如果這個子樹中的節點數已經超過b了,那麼這棵子樹本身就會成為乙個塊。既然我們確定了每棵子樹對這個節點的貢獻不會超過b,那麼我們每遍歷完乙個子樹就檢查一次,所以每個塊的範圍在[b,2b]之間,那麼為什麼給定的範圍強行是[b,3b]呢?因為最後剩餘的還要加進最後乙個塊,這樣構造我們可以發現每個塊中的節點都是相鄰的,這樣在塊中的兩點間距離的上界就是n??√了

這樣複雜度就***。

好了,我們會樹分塊了,莫隊演算法怎麼在樹上應用呢?其實是一樣的,我們對於乙個詢問操作記錄起始點和終點,每次l -> q[i].l,r -> q[i].r,排序依舊是那樣的。

sort(q + 1, q + m + 1, cmp); //對詢問進行排序

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

while(r != q[i].r)

//算出這次詢問的答案= =

}時間複雜度

加上演算法a)和演算法b),期望得分70。

非常好= =,我們已經拿到70分了。

d) 同樣,我們觀察第八和第九個測試點,我們可以發現差別在於這裡有修改操作了,好!我們如何處理修改操作呢?然後我們發現如果在b)演算法中強行安上修改那麼時間複雜度會變成o(n2),是不能ac這兩個測試點的,那麼怎麼ac呢?考慮在原來的莫隊中加上一維,表示修改的操作時間,如果加上一維,我們塊的大小就要變成o(n23)了,排序是前兩維按照塊的編號排序,最後一維從小到大排序。

我們在轉移的時候就變成的o(n23)了,於是轉移的時間複雜度就是o(n?n23)了,具體證明參見b)演算法的證明過程。那麼我們來算一算第三維轉移的時間複雜度,我們發現對於前兩維,每一維都有個n13塊,於是就有n23種情況,第三維的轉移每次都是o(n)的,所以轉移的時間複雜度就是o(n?n23)了,綜上所述,總的時間複雜度是o(n?n23),能通過這兩個測試點。

綜合以上四個思路,我們可以拿到90分了,演算法已經很優秀了。

e) 看到上面四個解法,我們思考一下最後這個點的解法,綜合解法c)和解法d)

vfleaking的解法,按照這個解法,我們發現最後我們只需要暴力的轉移即可,我們 發現最後這個式子是我們想要的答案,於是我們將d)的解法轉移到樹上!我們就 可以拿到100分了!

附上本弱的**

#include

#include

#include

#include

#include

using namespace std;

#define m 100100

#define ll long long

inline int read()

while('0' <= ch && ch <= '9')

return x * f;

}struct edge g[m * 2];

int head[m], tot;

int first[m];

int n, m, q;

int v[m], w[m], col[m], cnt[m];

int blo[m];

int st[m], top;

int height[m], ft[m][20];

int b, cnt_;

bool vis[m];

ll ansnow, ans[m];

struct node qr[m];

struct node

inline bool operator < (const node& rhs) const

} q[m];

inline void add(int a, int b);

inline void update(int x);

inline void modify(int x, int y);

inline void moveto(int x, int y);

inline void dfs(int x, int fa, int h);

inline void init();

inline int lca(int a, int b);

inline void getans(int x, int y);

int main()

b = pow(n, 2.0/3.0);//確定塊的大小

for(int i = 1; i <= n; i ++) col[i] = read(), first[i] = col[i];

//我們用鍊錶記錄每個點修改前和修改後的真實顏色

dfs(1, 0, 0); while(top) blo[st[top --]] = cnt_; init();

//對樹進行分塊

int totqr = 0, totq = 0;

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

else;

q[totq].sw(); //乙個小小的常數優化}}

sort(q + 1, q + totq + 1);

int tim = 1;

while(tim <= q[1].id)

moveto(q[1].x, q[1].y);getans(1, lca(q[1].x, q[1].y));

for(int i = 2; i <= totq; i ++)

for(int i = 1; i <= totq; i ++) printf("%lld\n", ans[i]);

return 0;

} inline void add(int a, int b);

head[a] = tot;

}inline void update(int x)

inline void modify(int x, int y)

inline void moveto(int x, int y)

}inline void dfs(int x, int fa, int h)}}

st[++ top] = x;

}inline void init()

}}inline int lca(int a, int b)

}if(a == b) return a;

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

} return ft[a][0];

}inline void getans(int x, int y)

bzoj 3052 糖果公園

題意 給出一顆n個結點的樹,每個結點上有一種糖果 1,m 乙個人經過這個結點品嚐糖果j獲得的愉悅度為w time j val j 其中time j 指j的品嚐次數 給出q次操作,操作有兩種 1 更改某結點的糖果種類 2 查詢某兩個結點路徑上的愉悅度總和 題解 250s的神題,orz各位神犇 將樹分塊...

BZOJ 3052 糖果公園

uoj 58 把樹轉化為尤拉序,把詢問對映到尤拉序上,在尤拉序上跑帶修改莫隊。具體的做法可以參考 國家集訓隊2014 集.pdf 的第82頁描述的性質。include include include include include using namespace std const int maxn...

BZOJ 3052 糖果公園 樹上帶修改莫隊

time limit 200 sec memory limit 512 mb submit 1264 solved 637 submit status discuss sample input 84131 2784 submit status discuss home back 這道題我很快的寫完了...