51nod1462 樹據結構

2021-07-29 05:14:09 字數 1281 閱讀 8482

給一顆以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位整數不會爆。

我們考慮用樹剖來做這道題。

對於乙個操作x,我們用樹鏈剖分,但現在問題來了,怎樣維護v和t呢?

我們對於線段樹的每一位存下乙個v,v1,t分別表示僅在該子樹擁有的操作1,該子樹及其父親傳下的操作1以及該子樹同時擁有t。每一次操作有乙個lzv,lzt表示懶標記下傳。下傳時v1 son+=lzv,lzv son+=lzv,t son+=t+lzt*v,lzt son+=t+lzt*v,最後把lzt,lzv,t清零。

#include

#include

#include

#include

#include

#define ll long long

using namespace std;

const int maxn=6e5+5;

struct codef[maxn];

int first[maxn],last[maxn],next[maxn],b[maxn],dfn[maxn],size[maxn],son[maxn],fa[maxn],top[maxn];

ll n,i,t,j,k,l,x,y,z,p,num,m,ans[maxn];

void lian(int

x,int

y)void dg(intx)}

void dg1(int

x)void make(int v)

void change(int l,int r,int v,int

x,int

y) if (l<=y && mid>=x) change(l,mid,v*2,x,y);

if (mid=x) change(mid+1,r,v*2+1,x,y);

}void find(int l,int r,int v)

find(l,mid,v*2);find(mid+1,r,v*2+1);

}int main()

find(1,n,1);

for (i=1;i<=n;i++)

printf("%lld\n",ans[i]);

}

51nod 1462 樹據結構

給出一棵n個點的樹,每個點有兩個權值v,t 有q個操作,有兩種操作 1.將x到根上的路徑上的點的v值都加上d 2.將x到根上的路徑上的點的t值都加上每個點的v值 d 最後求出所有點的t值 顯然可以直接樹鏈剖分做,不過lazy標記下放真麻煩,因為操作有互相影響 發現一種神標記方法 用矩陣 對於乙個點,...

51nod 1737 樹的重心

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

51 nod 蘋果曼和樹

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