題意:維護一棵樹,要求可以支援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,他想知道改...