HAOI2015 T2 樹狀陣列

2021-08-06 01:22:51 字數 1380 閱讀 1528

題意:維護一棵樹,要求可以支援1:單點權值加,2:以某點為根的子樹中的所有點權值加,3:詢問某點到根路徑上的點權和

分析:

法1:樹鏈剖分,以後來補吧…

法2:線段樹 , 與下面的大相徑庭

法3:樹狀陣列維護尤拉序列。

差分的思想與dfs序結合,i點在dfs序中的位置(進出等價)的字首和就是i到根的權值和。

對於第乙個操作,在in[i]加,out[i]+1減即可。

第二個操作怎麼辦呢,難道要暴力加?那不就達到o(n * n * log2n)了嗎,換個思路。

假設點x的子樹下某個點為y,那麼這次操作造成對以後的詢問造成的影響是,使3(y)的答案增加了 d * (depth[y] - depth[x] + 1) , 拆開 d * (depth[y]+1) - d * depth[x],後面顯然跟操作1等價,而前面不僅跟d有關,也和depth[y]以及y的位置有關,這裡的y很多,不可能挨個加。

總結一下,現在的修改對每個y都有影響,而且都不同,但是稍加分析卻可以發現它們有相同之處,可以用它解題。考慮到depth[y]其實是不用去找的,只需要在詢問時用即可。那麼有影響的只有d,對d進行操作就可以啦!很簡單,再開乙個樹狀陣列來維護即可。

(為了清晰 **中開了3個樹狀陣列)

#include

#include

#include

#include

using

namespace

std;

typedef

int _int;

#define int long long

const

int lim = 200005;

int n , m , a[lim];

vector

edge[lim];

struct treearray

void add(int i , int d)

int query(int i)

} ta[3];

int in[lim] , out[lim] , depth[lim] , sign;

void dfs(int x , int fa)

out[x] = ++ sign;

}_int main()

depth[1] = 1;

dfs(1 , 0);

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

ta[0].add(in[i] , a[i]),

ta[0].add(out[i]+1 , -a[i]);

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

else

if(ord == 2)

else

}return

0;}

HAOI2015 陣列遊戲

題目大意 有一排n個格仔,每個格仔上都有乙個白子或黑子,在上面進行遊戲,規則如下 選擇乙個含白子的格仔x,並選擇乙個數k,翻轉x,2x,kx格仔上的子。不能操作者負。思路 將 某個格仔上有乙個白子 視作遊戲的乙個狀態。對於狀態x,sg x mex。由於sg函式的取值只與棋盤大小和棋子位置有關,因此我...

HAOI2004 數列 樹狀陣列

乙個簡單的數列問題 給定乙個長度為n的數列,求這樣的三個元素ai,aj,ak的個數,滿足ai aj ak,且i j k。第一行是乙個整數n n 50000 第二行n個整數ai 0 ai 50000 乙個數,滿足ai aj ak i j k 的個數。5 1 2 3 4 1 用樹狀陣列求出二元組以及逆序...

11 01T2 樹狀陣列維護動態LIS

描述當一陣風吹來,風箏飛上天空,為了你,而祈禱,而祝福,而感動 oyiya 在 ak 了 ioi 之後來到了鄉下,在田野中玩耍,放鬆身心。他發現前面有一排小朋友在放風箏,每乙個風箏有乙個高度 hi,風箏的高度可能會隨著小朋友的心情而改變。這時,毒瘤的 oyiya 有了乙個毒瘤的 idea,他想知道改...