BJ模擬 鏈上求和 樹狀陣列維護dfs序

2021-08-18 14:21:27 字數 1480 閱讀 2113

題目描述:

給一棵n個節點的帶點權的樹,求: ∑x

=1n∑

y=x+

1n∑d

is(x

,y)+

1k=1

(路徑x

−y上前

k大點的

點權和)

∑ x=

1n∑y

=x+1

n∑k=

1dis

(x,y

)+1(

路徑x−

y上前k

大點的點

權和

)解題思路:

乙個節點的權值會被計算所有鏈上點權小等於它的點數次。

我們把點按權值從小到大排序後依次插入,對於插入的點

u u

,分情況討論之前插入的乙個點

v' role="presentation">vv對

u u

的次數貢獻(v在

子樹內或

v是u的

祖先' role="presentation">v在子

樹內或v

是u的祖

先v在子

樹內或v

是u的祖

先),用樹狀陣列維護即可,具體可以自己畫圖推推再結合**。

#include

#define ll long long

using namespace std;

int getint()

const

int n=100005,mod=1e9+7;

int n,ans;

struct nodea[n];

inline bool

operator

< (const node &a,const node &b)

inline ll query(int i)

inline void add(int l,int r,int v)

inline ll query(int l,int r)

}bit1,bit2,bit3;

void add(int x,int y)

void dfs(int u)

out[u]=idx;

}int calc(int u,int w)

else

}bit1.add(in[u],size[u]);

bit2.add(in[u],out[u],size[u]),bit3.add(in[u],out[u],1);

for(int e=first[u];e;e=nxt[e])

return res*w%mod;

}int main()

; dfs(1),sort(a+1,a+n+1);

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

ans=(ans+calc(a[i].id,a[i].val))%mod;

cout<'\n';

return

0;}

BJ模擬(1) D2T3 鏈上求和

鏈上求和 題目背景 分析 這個題,我真的很想呵呵,當時聽滿分神犇講了一次,然後學長講了一次,然後默默的自己看了 n次,然後在給別人講了兩次,才終於算是基本懂了 現在讓我寫,恐怕還是只有呵呵 我們先一步步進行考慮,首先對於一條鏈上的某乙個點,他在這一條鏈上的統計次數,是這條鏈上比它的權值小的點的個數加...

D 區間求和 數學 樹狀陣列

題意 求 sum n sum sum n 區間前k大值和 比賽時因為被b卡了沒有深入想這道題 結果b沒做出來後面的題也沒做 化一下式子 begin sum n sum n sum r a k cdot 1 sum r a i a k 考慮乙個數的貢獻 sum n sum n a k cdot a i...

NOIP模擬 相交(樹鏈剖分 樹狀陣列維護)

我已經無力爆粗了。md這c 怎麼能在編譯了 執行了以後,最後發現居然是之前的版本?喵喵喵?考慮兩條路徑相交,那麼其中一條的lca一定在另一條路徑上。所以開兩個樹狀陣列維護之前路徑的資訊和之前路徑的lca的位置。統計一下,然後更新,再做下一條路徑即可。includeusing namespace st...