【HDU】5221 Occupation【树链剖分】
来源:互联网 发布:课堂随机点名软件 编辑:程序博客网 时间:2024/06/18 08:12
传送门:【HDU】5221 Occupation
题目分析:
最直接的想法,用一棵树链剖分维护路径,一棵dfs序线段树维护子树。因为每次最多修改一个点,所以修改的时候我们暴力修改每个点就可以了。
#pragma comment(linker, "/STACK:102400000,102400000")#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )#define ls ( o << 1 )#define rs ( o << 1 | 1 )#define lson ls , l , m#define rson rs , m + 1 , r#define root 1 , 1 , n#define mid ( ( l + r ) >> 1 )const int MAXN = 100005 ;const int MAXE = 200005 ;const int INF = 0x3f3f3f3f ;struct Edge { int v , n ; Edge () {} Edge ( int v , int n ) : v ( v ) , n ( n ) {}} ;Edge E[MAXE] ;int H[MAXN] , cntE ;int tpos[2][MAXN << 2] ;int tin[2][MAXN] ;int top[MAXN] ;int siz[MAXN] ;int pre[MAXN] ;int dep[MAXN] ;int pos[MAXN] ;int son[MAXN] ;int val[MAXN] ;int dfs_clock ;int idx[MAXN] ;int ou[MAXN] ;bool c[MAXN] ;int tree_idx ;int n , q ;int ans ;void init () { ans = 0 ; cntE = 0 ; tree_idx = 0 ; dfs_clock = 0 ; clr ( H , -1 ) ;}void addedge ( int u , int v ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ;}void dfs ( int u ) { idx[u] = ++ dfs_clock ; tin[1][dfs_clock] = u ; siz[u] = 1 ; son[u] = 0 ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v == pre[u] ) continue ; pre[v] = u ; dep[v] = dep[u] + 1 ; dfs ( v ) ; siz[u] += siz[v] ; if ( siz[son[u]] < siz[v] ) son[u] = v ; } ou[u] = dfs_clock ;}void rebuild ( int u , int top_element ) { top[u] = top_element ; pos[u] = ++ tree_idx ; tin[0][tree_idx] = u ; if ( son[u] ) rebuild ( son[u] , top_element ) ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v != pre[u] && v != son[u] ) rebuild ( v , v ) ; }}void build ( int o , int l , int r ) { if ( l == r ) { tpos[0][o] = tin[0][l] ; tpos[1][o] = tin[1][l] ; return ; } int m = mid ; build ( lson ) ; build ( rson ) ; tpos[0][o] = max ( tpos[0][ls] , tpos[0][rs] ) ; tpos[1][o] = max ( tpos[1][ls] , tpos[1][rs] ) ;}void update ( int x , int i , int v , int o , int l , int r ) { if ( l == r ) { tpos[i][o] = v ? tin[i][l] : 0 ; return ; } int m = mid ; if ( x <= m ) update ( x , i , v , lson ) ; else update ( x , i , v , rson ) ; tpos[i][o] = max ( tpos[i][ls] , tpos[i][rs] ) ;}int query ( int L , int R , int i , int o , int l , int r ) { if ( L <= l && r <= R ) return tpos[i][o] ; int m = mid ; if ( R <= m ) return query ( L , R , i , lson ) ; if ( m < L ) return query ( L , R , i , rson ) ; return max ( query ( L , R , i , lson ) , query ( L , R , i , rson ) ) ;}void Update1 ( int x , int y ) { while ( top[x] != top[y] ) { if ( dep[top[x]] < dep[top[y]] ) swap ( x , y ) ; while ( 1 ) { int t = query ( pos[top[x]] , pos[x] , 0 , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 , 0 , root ) ; update ( idx[t] , 1 , 0 , root ) ; ans += val[t] ; //printf ( "%d\n" , t ) ; } x = pre[top[x]] ; } if ( dep[x] > dep[y] ) swap ( x , y ) ; while ( 1 ) { int t = query ( pos[x] , pos[y] , 0 , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 , 0 , root ) ; update ( idx[t] , 1 , 0 , root ) ; ans += val[t] ; }}void Update2 ( int L , int R ) { while ( 1 ) { int t = query ( L , R , 1 , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 , 0 , root ) ; update ( idx[t] , 1 , 0 , root ) ; ans += val[t] ; }}void solve () { int u , v , op ; init () ; scanf ( "%d" , &n ) ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d" , &val[i] ) ; c[i] = 1 ; } for ( int i = 1 ; i < n ; ++ i ) { scanf ( "%d%d" , &u , &v ) ; addedge ( u , v ) ; addedge ( v , u ) ; } dfs ( 1 ) ; rebuild ( 1 , 1 ) ; build ( root ) ; scanf ( "%d" , &q ) ; for ( int i = 0 ; i < q ; ++ i ) { scanf ( "%d" , &op ) ; if ( op == 1 ) { scanf ( "%d%d" , &u , &v ) ; Update1 ( u , v ) ; } else if ( op == 2 ) { scanf ( "%d" , &u ) ; if ( !c[u] ) { c[u] = 1 ; update ( pos[u] , 0 , 1 , root ) ; update ( idx[u] , 1 , 1 , root ) ; ans -= val[u] ; } } else { scanf ( "%d" , &u ) ; Update2 ( idx[u] , ou[u] ) ; } printf ( "%d\n" , ans ) ; }}int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ;}
然而我们可以发现,树链剖分是有dfs序,然后我们就可以发现对于一个节点的子树,其子树构成的区间也是连续的,那么我们只需要一个树链剖分就够了。
#pragma comment(linker, "/STACK:102400000,102400000")#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>using namespace std ;typedef long long LL ;#define clr( a , x ) memset ( a , x , sizeof a )#define cpy( a , x ) memcpy ( a , x , sizeof a )#define ls ( o << 1 )#define rs ( o << 1 | 1 )#define lson ls , l , m#define rson rs , m + 1 , r#define root 1 , 1 , n#define mid ( ( l + r ) >> 1 )const int MAXN = 100005 ;const int MAXE = 200005 ;const int INF = 0x3f3f3f3f ;struct Edge { int v , n ; Edge () {} Edge ( int v , int n ) : v ( v ) , n ( n ) {}} ;Edge E[MAXE] ;int H[MAXN] , cntE ;int tpos[MAXN << 2] ;int tree[MAXN] ;int top[MAXN] ;int siz[MAXN] ;int pre[MAXN] ;int dep[MAXN] ;int pos[MAXN] ;int son[MAXN] ;int val[MAXN] ;int idx[MAXN] ;int dfs_clock ;bool c[MAXN] ;int tree_idx ;int in[MAXN] ;int ou[MAXN] ;int n , q ;int ans ;void init () { ans = 0 ; cntE = 0 ; tree_idx = 0 ; dfs_clock = 0 ; clr ( H , -1 ) ;}void addedge ( int u , int v ) { E[cntE] = Edge ( v , H[u] ) ; H[u] = cntE ++ ;}void dfs ( int u ) { siz[u] = 1 ; son[u] = 0 ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v == pre[u] ) continue ; pre[v] = u ; dep[v] = dep[u] + 1 ; dfs ( v ) ; siz[u] += siz[v] ; if ( siz[son[u]] < siz[v] ) son[u] = v ; } ou[u] = dfs_clock ;}void rebuild ( int u , int top_element ) { in[u] = ++ dfs_clock ; top[u] = top_element ; pos[u] = ++ tree_idx ; idx[tree_idx] = u ; if ( son[u] ) rebuild ( son[u] , top_element ) ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( v != pre[u] && v != son[u] ) rebuild ( v , v ) ; } ou[u] = dfs_clock ;}void build ( int o , int l , int r ) { tpos[o] = idx[l] ; if ( l == r ) { tree[l] = o ; return ; } int m = mid ; build ( lson ) ; build ( rson ) ;}void update ( int x , int v ) { int o = tree[x] ; tpos[o] = v ? idx[x] : 0 ; while ( o > 1 ) { o >>= 1 ; tpos[o] = max ( tpos[ls] , tpos[rs] ) ; }}int query ( int L , int R , int o , int l , int r ) { if ( L <= l && r <= R ) return tpos[o] ; int m = mid ; if ( R <= m ) return query ( L , R , lson ) ; if ( m < L ) return query ( L , R , rson ) ; return max ( query ( L , R , lson ) , query ( L , R , rson ) ) ;}void Update1 ( int x , int y ) { while ( top[x] != top[y] ) { if ( dep[top[x]] < dep[top[y]] ) swap ( x , y ) ; while ( 1 ) { int t = query ( pos[top[x]] , pos[x] , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 ) ; ans += val[t] ; //printf ( "%d\n" , t ) ; } x = pre[top[x]] ; } if ( dep[x] > dep[y] ) swap ( x , y ) ; while ( 1 ) { int t = query ( pos[x] , pos[y] , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 ) ; ans += val[t] ; }}void Update2 ( int L , int R ) { while ( 1 ) { int t = query ( L , R , root ) ; if ( !t ) break ; c[t] = 0 ; update ( pos[t] , 0 ) ; ans += val[t] ; }}void solve () { int u , v , op ; init () ; scanf ( "%d" , &n ) ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d" , &val[i] ) ; c[i] = 1 ; } for ( int i = 1 ; i < n ; ++ i ) { scanf ( "%d%d" , &u , &v ) ; addedge ( u , v ) ; addedge ( v , u ) ; } dfs ( 1 ) ; rebuild ( 1 , 1 ) ; build ( root ) ; scanf ( "%d" , &q ) ; for ( int i = 0 ; i < q ; ++ i ) { scanf ( "%d" , &op ) ; if ( op == 1 ) { scanf ( "%d%d" , &u , &v ) ; Update1 ( u , v ) ; } else if ( op == 2 ) { scanf ( "%d" , &u ) ; if ( !c[u] ) { c[u] = 1 ; update ( pos[u] , 1 ) ; ans -= val[u] ; } } else { scanf ( "%d" , &u ) ; Update2 ( in[u] , ou[u] ) ; } printf ( "%d\n" , ans ) ; }}int main () { int T ; scanf ( "%d" , &T ) ; for ( int i = 1 ; i <= T ; ++ i ) { solve () ; } return 0 ;}
0 0
- 【HDU】5221 Occupation【树链剖分】
- hdu 5221 Occupation(树链剖分)
- HDU 5221 Occupation(树链剖分)
- HDU 5221 Occupation(树链剖分)
- 【HDU 5221】 Occupation 【树链剖分+线段树】
- hdu 5221 Occupation
- HDU 5221 Occupation
- Hdu 5221 Occupation
- HDU 5221 Occupation dfs序版树链剖分
- hdu 5221 Occupation (树剖+线段树)
- "BestCoder"杯中国大学生程序设计冠军赛 HDU 5221 Occupation
- 树链剖分 - hdu5221 Occupation
- HDU5221 Occupation【树链剖分+线段树】
- HDU 5221 树链剖分
- hdu 4729 树链剖分+二分
- HDU 3966 树链剖分
- hdu 3966 树链剖分模版
- HDU 5044 Tree 树链剖分
- 两个链表的第一个公共结点
- LeetCode | Minimum Path Sum
- MySQL部分解疑
- 【ExtJs】柱状图,改变每条柱子的颜色
- 从一个菜鸟开始学习机器学习
- 【HDU】5221 Occupation【树链剖分】
- 流随机访问
- Windows版OpenVPN安装、配置教程
- Ruby七天入门(2 函数,数组和类)
- STL--迭代器--原理与实践
- 网络营销公司,一站式网络营销服务
- android点滴
- Unity3D的断点调试功能
- 不要过早的释放动态内存空间