51nod 1462 樹據結構

2022-05-20 18:23:36 字數 2034 閱讀 1377

給出一棵n個點的樹,每個點有兩個權值v,t

有q個操作,有兩種操作:

1.將x到根上的路徑上的點的v值都加上d

2.將x到根上的路徑上的點的t值都加上每個點的v值*d

最後求出所有點的t值

顯然可以直接樹鏈剖分做,不過lazy標記下放真麻煩,因為操作有互相影響

發現一種神標記方法——用矩陣

對於乙個點,它的資訊表示為$$ \begin 1 & 0 & 0 \\ 0 & 1 & 0 \\ v & t & 1 \\ \end $$

而對於第一種操作,就將點的資訊乘上$$ \begin 1 & 0 & 0 \\ 0 & 1 & 0 \\ d & 0 & 1 \\ \end $$

而第二種操作則乘上$$ \begin 1 & d & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end $$

這樣就不用擔心互相影響了,因為矩陣乘法滿足結合律,所以直接將操作按順序乘起來就行了

聽說可以離線cdq做

#include#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;struct

trnode

tr[210000];int

trlen;

struct

matrix

}d[210000

],cmp;

matrix multi(matrix a,matrix b)}}

returnc;}

void bt(int l,intr)}

struct

node

a[110000];int len,last[110000

];void ins(int x,int y);last[x]=len;}

int son[110000],tot[110000

];void dfs1(intx)}

int top[110000],ys[110000

],z;

void dfs2(int x,int

tp)}

void update(int

now)

void change(int now,int l,int

r)

int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2

; update(now);

if(r<=mid) change(lc,l,r);

else

if(l>mid) change(rc,l,r);

else change(lc,l,mid),change(rc,mid+1

,r);

}int fa[110000

];void solve(intx)}

ll d[

110000

];void

out(int

now)

int lc=tr[now].lc,rc=tr[now].rc;

update(now);

if(lc!=-1) out

(lc);

if(rc!=-1) out

(rc);

}int

main()

dfs1(1);

z=0;dfs2(1,1

); trlen=0;bt(1

,z);

cmp.a[

1][1]=cmp.a[2][2]=cmp.a[3][3]=1

;

intq;

scanf("%d

",&q);

while(q--)

out(1

);

for(int i=1;i<=n;i++) printf("

%lld\n

",d[ys[i]]);

return0;

}

51nod1462 樹據結構

給一顆以1為根的樹。每個點有兩個權值 vi,ti,一開始全部是零。q次操作 讀入o,u,d o 1 對u到根上所有點的vi d o 2 對u到根上所有點的ti vi d 最後,輸出每個點的ti值 n,q 100000 有50 的資料n,q 10000 注 所有數64位整數不會爆。我們考慮用樹剖來做這...

51nod 1737 樹的重心

思路 樹的重心也叫樹的質心。找到乙個點,其所有的子樹中最大的子樹節點數最少,那麼這個點就是這棵樹的重心,刪去重心後,生成的多棵樹盡可能平衡。考慮每一條邊被統計進答案幾次,若斷開這條邊後樹形成大小為s1 s2的兩個聯通塊則這條邊最多被統計min s1,s2 次。刪去重心後任意同一聯通塊中的兩點不構成路...

51 nod 蘋果曼和樹

1500 蘋果曼和樹 基準時間限制 1 秒 空間限制 131072 kb 分值 80 難度 5 級演算法題 收藏 關注 蘋果曼有一棵 n個點的樹。有一些 至少乙個 結點被標記為黑色,有一些結點被標記為白色。現在考慮乙個包含 k 0 k n 條樹邊的集合。如果蘋果曼刪除這些邊,那麼會將這個樹分成 k ...