BZOJ 3779 重組病毒 LCT維護子樹資訊

2021-07-30 04:58:51 字數 2198 閱讀 3808

題目大意:給定一棵樹,要求支援:將某個點到根的路徑染色;換根後將原來的根到現在的根的路徑染色;求某個點的子樹到根的平均顏色段數

比較麻煩的lct維護子樹資訊

變數名是照neither_nor神犇抄的..意義相同,鏈結

因為要計算子樹到根的平均顏色段數,所以要維護子樹到(子樹的)根的顏色段數和(col),splay在原樹中代表的鏈的顏色段數(cols),子樹size(rsiz)。

其實就是把子樹到當前根的顏色段數和分成子樹到子樹根和子樹根到當前根兩部分。將想要查詢的子樹根access+splay後,col即為子樹內顏色段數和,cols即為子樹根到當前根。

而要維護col,就要維護coll/colr,sumcol,scol,sumcol

具體的更新關係為:

coll->col (update)

colr->coll (rev)

sumcol->coll/colr (color)

scol->col / sumscol->sumcol (color)

col->coll/colr (maintain)

col->sumcol / scol->sumscol (maintain)

coll->colr / colr->coll (maintain)

將變數整理後,

正常splay資訊:siz,v,lv,rv,cols

虛子樹資訊:xsiz,col,scol

lct子樹資訊:rsiz,coll,colr,sumcol,sumscol

#include 

#include

#define n 100005

#define int long long

using

namespace

std;

typedef

long

long ll;

struct node

///basic splay varieties

int siz,xsiz,rsiz,v,lv,rv,cols;

///color information

int coll,colr,col,sumcol,scol,sumscol;

///mark

int color_mark;

bool rev_mark;

///function

node();

void rev();

void color(int);

void pushdown();

void maintain();

void update(node*,int);

}*null=new node(),p[n];

node :: node():rev_mark(false),color_mark(0),xsiz(0)

void node :: rev()

void node :: color(int x)

void node :: pushdown()

if(color_mark)

return ;

} void node :: maintain()

if(ch[1]!=null)

return ;

} void node :: update(node* o,int k)

void rotate(node* o,int d)

void to_pushdown(node* o)

void splay(node* o)

return ;

} void access(node* o)

return ;

} void move_to_root(node* o)

void link(node* x,node* y)

int n,m,t;

void request(node* o)

void release(node* o)

void recenter(node* o)

main()

move_to_root(p+1);

while(m--)

return

0;

}

BZOJ3779 重組病毒

題目大意 給一棵樹,每個點一開始顏色互不相同,支援三個操作 1.將乙個點到根的路徑染成一種新的顏色 2.將乙個新的點設為根,並將原來的根到這個點的路徑染成一種新的顏色 3.查詢乙個子樹 對於當前根 到根的路徑期望顏色數 真tm是道神題,idea實在是太妙了 首先由於第2個操作的特殊性,我們可以發現,...

BZOJ3779 重組病毒

窮哭了 難嗎?難碼.首先觀察一下操作一,就是乙個access,但是要改變子樹啊,lct不緇瓷,所以線段樹稍微維護一下。怎麼維護是乙個大難點啊。是要分類討論的。先找出實右子樹在原數上的根xxx。情況rt x rt x rt x 直接修改整顆樹。r trt rt在子樹中,令y r ty rt y rt ...

bzoj 3779 重組病毒

一道好題 乙個點到根傳染需要的時間是這段路徑上不同顏色的數目,乙個點子樹到根平均傳染時間就是加權平均數了 好像是廢話 所以只要用線段樹維護dfs序就這個可以了,換根的話乙個點的子樹要麼在dfs序中不變,要麼被截成了 1,l 和 r,n 兩段 當這個點為當前root的祖先 l和r即為包含當前根的這個點...