problem 2176 easy problem
accept: 38 submit: 119
time limit: 2000 msec memory limit : 32768 kb
problem description
給定一棵n個節點以1為根的樹,初始每個節點的值為0,現在我們要在樹上進行一些操作,操作有兩種型別。
1 x val 表示對以x為根的子樹的每個點進行加權操作(我們定義每個節點的深度為每個節點到根1的距離),如果 y是以x為根的子樹中的點那麼 y節點的權值增加 ((dep[y]-dep[x])%k+1)*val 其中dep[y]表示y節點的深度,k為乙個常數(1<=k<=5)
2 x 查詢當前x節點的權值。
input
首先輸入乙個整數t 表示資料的組數,每組資料 第一行有3個整數 n ,m, k(1<=n,m<=50000, 1<=k<=5) 。n表示節點數,m表示運算元,k表示如題目描述的常數。
接下去n-1行描述一棵樹。接下去m行每行表示 乙個操作 有兩種型別1 x val 表示第一種型別 2 x 表示第二種型別。(1<=x<=n,1<=val<=100)
output
每組資料首先輸出 case#x: 表示第x組資料 x從1開始。接下去對於每組資料中的每個查詢操作輸出查詢結果。(具體輸出格式看樣例)
sample input
1 5 7 2
1 2
2 4
2 5
1 31 2 3
1 1 2
2 1
2 2
2 3
2 4
2 5
sample output
case#1:
2 7
4 8
8由於k比較小,可以用k顆線段樹來維護整棵樹,對於每乙個操作1,因為是用dep%k來區分線段樹的,所以要根據y與x的關係來確定y所得到的值
#include
#include
#include
#include
#include
using
namespace
std ;
const
int n = 5e4 + 11 ;
const
int m = n<<1 ;
int head[n] , next[m] , end[m] ; int nedge ;
int ptt[n] , interval[n] ; int nptt ;
int tree[6][n<<2] ; int dep[n] ;
int n , m , k ;
int x1 , y1 ;
void add_edge(int a , int b)
void add_info()
}void dfs(int u , int fa)
}interval[u] = nptt ;
}void down(int mod , int site)
}void update(int mod ,int site ,int l , int r , int d)
down(mod ,site) ;
int mid = (l+r)>>1 ;
if(x1 <= mid) update(mod , site<<1 , l , mid , d) ;
if(y1 > mid) update(mod , site<<1|1 , mid+1 , r , d) ;
}void query(int mod , int site , int l , int r)
down(mod , site) ;
int mid = (l+r)>>1 ;
if(x1 <= mid) query(mod , site<<1 , l , mid) ;
if(y1 > mid) query(mod , site<<1|1 , mid+1 , r) ;
}int main()
}else }}
}
線段樹 經典 有趣
一種區間樹,即將除葉子節點的區間拆分成兩個區間,序列以一棵二叉樹的形式呈現。如圖便是一棵線段樹,我們將通過圖來更深刻的認識線段樹。1.可以觀察到,這棵線段樹的深度是 log n 2.每個除葉子節點以外節點的左孩子是該節點乘上 2 而右孩子是該節點乘上 2 加上 1 3.可以觀察到此樹是一棵完全二叉樹...
FZU 2277 線段樹 DFS序
對一棵樹進行操作,1 v x k代表對根節點v加x,對v的子節點加x k,對孫子節點加v 2k。2 v代表查詢節點v的值。其實是乙個很簡單的線段樹,對於一次增加操作,節點x增加的值其實就是x deep x deep v k。deep v 為該次修改的根節點 查詢的時候單點查詢,也不用pushdown...
fzu 2105 線段樹區間更新
題意 區間有三種二進位制操作,區間中的值不超過16,然後查詢區間和。因為每個數很小,所以區間內存在大量重複值,並且經過二進位制操作後區間中相等的值會越來越多。我們只需要記錄當前區間中的值是否相等即可。include include include include using namespace st...