bzoj 4147 Abs 熟練剖分

2021-08-08 06:34:04 字數 1937 閱讀 1337

題目描述

給定一棵樹,設計資料結構支援以下操作

1 u v d 表示將路徑 (u,v) 加d

2 u v 表示詢問路徑 (u,v) 上點權絕對值的和

輸入

第一行兩個整數n和m,表示結點個數和運算元

接下來一行n個整數a_i,表示點i的權值

接下來n-1行,每行兩個整數u,v表示存在一條(u,v)的邊

接下來m行,每行乙個操作,輸入格式見題目描述

輸出

對於每個詢問輸出答案

樣例輸入

4 4

-4 1 5 -2

1 22 3

3 42 1 3

1 1 4 3

2 1 3

2 3 4

樣例輸出

10

139

題解:區 間 動 態 修 改+區 間 動 態 查 詢,很明顯的樹鏈剖分裸題,唯一的難點就是引入了負數和絕對值,仔細分析一下不難發現:對於一段區間如果全是正數則直接打標記,如果有正數有負數且沒有「負數變正數的情況」,那麼則加上(正數的個數-負數的個數)*flag,對於既存在負數和正數有存在「負數邊正數的情況」,那麼遞迴兩個區間進行修改和查詢。維護三個陣列:sum:區間絕對值之和,val區間最小負數的絕對值,si正數個數-負數的個數。

總結:當分析出題目的難點和知識點後需要將其分離開來,將難點單獨分析,且要抓住難點主要難在什麼地方,能否分情況討論來減弱難度甚至消除難點。線段樹區間維護的資訊可以很靈活,根據題目中的要求合理開陣列進行維護。

#include #include #include #define n 100010

#define lson l , mid , x << 1

#define rson mid + 1 , r , x << 1 | 1

using namespace std;

typedef long long ll;

const int inf = 1 << 30;

int a[n] , head[n] , to[n << 1] , next[n << 1] , cnt , fa[n] , deep[n] , sv[n] , bl[n] , pos[n] , tot , v[n];

int n , val[n << 2] , si[n << 2] , add[n << 2];

ll sum[n << 2];

void addedge(int x , int y)

void dfs1(int x)

void dfs2(int x , int c)

}void pushup(int x)

void pushdown(int x)

}void build(int l , int r , int x)

int mid = (l + r) >> 1;

build(lson) , build(rson);

pushup(x);

}void update(int b , int e , int a , int l , int r , int x)

}ll query(int b , int e , int l , int r , int x)

int main()

return 0;

}

概率 樹規 熟練剖分

根節點不一定是1,但是是乙個確定的點,看誰不是兒子就行了。這道題我們考慮從兒子推到根。設f i j 表示以i為根的子樹中,最長輕鏈長度為j的概率。因為每乙個son被選為重兒子的概率相同,且重兒子對父親貢獻和輕兒子不同,所以要每乙個點為重兒子,之後挨個列舉每個兒子。這個效率是n 2,然後要列舉鏈的長度...

bzoj4127 Abs 樹鏈剖分 線段樹

abs bzoj 4127 題目大意 給定一棵數,支援鏈加和鏈上權值的絕對值的和。注釋 1 le n,m le 10 5 delta ge 0 a i le 10 8 想法 看完題,以為又是什麼資料結構裸題。然後發現絕對值.臥槽?啥jb玩意兒?絕對值?這怎麼加?開始的想法是維護乙個do標記,表示這個...

樹鏈剖分 bzoj2243

time limit 20 sec memory limit 512 mb submit 2492 solved 960 submit status 給定一棵有n個節點的無根樹和m個操作,操作有2類 1 將節點a到節點b路徑上所有點都染成顏色c 2 詢問節點a到節點b路徑上的顏色段數量 連續相同顏色...