1. 程式人生 > >HDU 1698 Just a Hook 線段樹 區間更新

HDU 1698 Just a Hook 線段樹 區間更新

不同 描述 感覺 ring 這也 deque deb %d total

  題目鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=1698

  題目描述: 區間更新, 最後求出1 ~ n 之和  

  解題思路: 這裏涉及到區間更新, 這也是我第一次寫區間更新, 以前都是單點更新, 回溯就可以了, 如果將區間更新化成區間長度的單點更新, 復雜度會很大, 所以這裏使用了懶惰標記的方法來解決這個問題。 懶惰標記, 顧名思義就是放著不管, 簡單來說就是區間更新是不向下更新, 先打一個標記, 等下次更新或者查詢的時候才向下更新一步, (同理打懶惰標記)。

  代碼:

技術分享
#include <iostream>
#include 
<cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 using
namespace std; int cases; const int maxn = 1e5+10; int n; int tree[maxn<<2]; int col[maxn<<2]; void Pushup( int rt ) { tree[rt] = tree[rt<<1] + tree[rt<<1|1]; } void Pushdown( int rt, int m ) { if( col[rt] ) { col[rt<<1] = col[rt<<1|1] = col[rt]; tree[rt
<<1] = (m-(m >> 1)) * col[rt]; tree[rt<<1|1] = (m >> 1) * col[rt]; col[rt] = 0; } } void build( int l, int r, int rt ) { col[rt] = 0; tree[rt] = 1; if( l == r ) return; int m = (l + r) >> 1; build( lson ); build( rson ); Pushup(rt); } void Update( int L, int R, int x, int l, int r, int rt ) { if( L <= l && r <= R ) { col[rt] = x; tree[rt] = x * (r-l+1); return; } Pushdown( rt, r-l+1 ); int m = (l + r) >> 1; if( L <= m ) Update( L, R, x, lson ); if( R > m ) Update( L, R, x, rson ); Pushup( rt ); return; } void debug() { for( int i = 1; i <= 40; i++ ) { cout << tree[i] << " "; } cout << endl; for( int i = 1; i <= 40; i++ ) { cout << col[i] << " "; } cout << endl; } int main() { int t; scanf( "%d", &t ); cases = 1; while( t-- ) { scanf( "%d", &n ); build( 1, n, 1 ); debug(); int m; scanf( "%d", &m ); for( int i = 0; i < m; i++ ) { int a, b, c; scanf( "%d%d%d", &a, &b, &c ); Update( a, b, c, 1, n, 1 ); debug(); } // debug(); // cout << "===" << endl; printf( "Case %d: The total value of the hook is %d.\n", cases++, tree[1] ); } return 0; }
View Code

  思考: 這個懶惰標記很巧妙, 我一時間沒有弄懂, 今天上午把函數調用過程全部寫出來才感覺稍微有一點明白原理了,每次update函數就是先判定是否當前判定區間在給定區間中, 如果在,給該區間的根節點打上懶惰標記,( 本題中懶惰標記就是鉤子的上色), 只更新當期根節點的值, 如果不在, {如果當前根節點標記有懶惰標記, 將懶惰標記傳給兩個兒子並且取消當前根節點的懶惰標記, 當然同時只更新兩個兒子的值如果當前根節點沒有懶惰標記, 什麽也不做}, 然後就是分治左右區間, 在函數回溯的時候更新區間和。

  想了好久, 現在腦子還是有點兒亂, 遇到不同的題再想吧

HDU 1698 Just a Hook 線段樹 區間更新