hdu 5052 树链剖分+线段树+区间合并
来源:互联网 发布:只有我不在的街道知乎 编辑:程序博客网 时间:2024/06/06 21:38
各种裸,但合在一起好恶心...
因为路径是有向的,所以要维护区间里向两个方向走的最大收益和区间里的最大最小值,要用到区间合并的线段树
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#define MAX 50007#define INF 1<<30using namespace std;int t,n,m;int a[MAX];struct Edge{ int v , next;}e[MAX<<1];int head[MAX];int cc;void add ( int u , int v ){ e[cc].v = v; e[cc].next = head[u]; head[u] = cc++;}int siz[MAX],dep[MAX],top[MAX],tid[MAX],rank[MAX],fa[MAX],tim,son[MAX];void dfs1 ( int u = 1 , int p = 0 , int d = 0 ){ siz[u] = 1 , dep[u] = d; fa[u] = p; for ( int i = head[u] ; ~i ; i = e[i].next ) { int v = e[i].v; if ( v == p ) continue; dfs1 ( v , u , d+1 ); siz[u] += siz[v]; if ( son[u] == -1 || siz[v] > siz[son[u]] ) son[u] = v; }}void dfs2 ( int u = 1 , int tp = 1 ){ top[u] = tp , tid[u] = ++tim; rank[tid[u]] = u; if ( son[u] == -1 ) return; dfs2 ( son[u] , tp ); for ( int i = head[u] ; ~i ; i = e[i].next ) { int v = e[i].v; if ( v == fa[u] || v == son[u] ) continue; dfs2 ( v , v ); }}struct Tree{ int l , r , mx , mi , lmx , rmx , lazy;}tree[MAX<<2];void push_up ( int u ){ tree[u].mx = max ( tree[u<<1].mx , tree[u<<1|1].mx ); tree[u].mi = min ( tree[u<<1].mi , tree[u<<1|1].mi ); tree[u].lmx = max ( tree[u<<1].lmx , tree[u<<1|1].lmx ); tree[u].lmx = max ( tree[u].lmx , tree[u<<1].mx - tree[u<<1|1].mi ); tree[u].rmx = max ( tree[u<<1].rmx , tree[u<<1|1].rmx ); tree[u].rmx = max ( tree[u].rmx , tree[u<<1|1].mx - tree[u<<1].mi );}void push_down ( int u ){ int lazy = tree[u].lazy; if ( lazy ) { tree[u].lazy = 0; tree[u<<1].lazy += lazy; tree[u<<1|1].lazy += lazy; tree[u<<1].mx += lazy; tree[u<<1].mi += lazy; tree[u<<1|1].mx += lazy; tree[u<<1|1].mi += lazy; }}void build ( int u , int l , int r ){ tree[u].l = l , tree[u].r = r; tree[u].lazy = 0; if ( l == r ) { tree[u].mx = a[rank[l]]; tree[u].mi = a[rank[l]]; tree[u].lmx = 0; tree[u].rmx = 0; return; } int mid = l + r >> 1; build ( u<<1 , l , mid ); build ( u<<1|1 , mid+1 , r ); push_up ( u );}void update ( int u , int left , int right , int v ){ int l = tree[u].l , r = tree[u].r; if ( left <= l && r <= right ) { tree[u].mx += v; tree[u].mi += v; tree[u].lazy += v; return; } push_down ( u ); int mid = l + r >> 1; if ( left <= mid ) update ( u<<1 , left , right , v ); if ( right > mid ) update ( u<<1|1 , left , right , v ); push_up ( u );}int query ( int u , int left , int right , int flag , int&tmax , int&tmin ){ int l = tree[u].l , r = tree[u].r; if ( left <= l && r <= right ) { tmax = tree[u].mx; tmin = tree[u].mi; if ( flag ) return tree[u].lmx; else return tree[u].rmx; } push_down ( u ); int mid = l + r >> 1; if ( right <= mid ) return query ( u<<1 , left , right , flag , tmax , tmin ); else if ( left > mid ) return query ( u<<1|1 , left , right , flag , tmax , tmin ); else { int maxl , maxr , minl , minr; int res = max ( query ( u<<1 , left , right, flag , maxl , minl ), query ( u<<1|1 , left , right , flag , maxr , minr ) ); tmax = max ( maxl , maxr ); tmin = min ( minl , minr ); if ( flag ) return max ( res , maxl - minr ); else return max ( res , maxr - minl ); } }void change ( int x , int y , int v ){ while ( top[x] != top[y] ) { if ( dep[top[x]] < dep[top[y]] ) swap ( x , y ); update ( 1 , tid[top[x]] , tid[x] , v ); x = fa[top[x]]; } if ( dep[x] > dep[y] ) swap ( x, y ); update ( 1 , tid[x] , tid[y] , v );}int get ( int x , int y ){ int tmax , tmin , maxl , minl , maxr , minr; maxl = maxr = -INF; minl = minr = INF; int ret = -INF; while ( top[x] != top[y] ) { if ( dep[top[x]] > dep[top[y]] ) { ret = max ( ret , query ( 1 , tid[top[x]] , tid[x] , 1 , tmax , tmin ) ); ret = max ( ret , tmax - minl ); maxl = max ( maxl , tmax ); minl = min ( minl , tmin ); x = fa[top[x]]; } else { ret = max ( ret , query ( 1 , tid[top[y]] , tid[y] , 0 , tmax , tmin ) ); ret = max ( ret , maxr - tmin ); maxr = max ( maxr , tmax ); minr = min ( minr , tmin ); y = fa[top[y]]; } } if ( dep[x] > dep[y] ) ret = max ( ret , query ( 1 , tid[y] , tid[x] , 1 , tmax , tmin ) ); else ret = max ( ret , query ( 1 , tid[x] , tid[y] , 0 , tmax , tmin ) ); ret = max ( ret , tmax - minl ); ret = max ( ret , maxr - tmin ); ret = max ( ret , maxr - minl ); return ret;}int main ( ){ scanf ( "%d" , &t ); while ( t-- ) { scanf ( "%d" , &n ); for ( int i = 1 ; i <= n ; i++ ) scanf ( "%d" , &a[i] ); int u , v ; memset ( head , -1 , sizeof (head)); cc = 0; for ( int i = 1 ; i < n ; i++ ) { scanf ( "%d%d" , &u , &v ); add ( u , v ); add ( v , u ); } tim = 0; memset ( son , -1 , sizeof ( son ) ); dfs1 ( 1 , 0 , 0); dfs2 ( 1 , 1 ); build ( 1 , 1 , n ); scanf ( "%d" , &m ); int c; for ( int i = 0 ; i < m ; i++ ) { scanf ( "%d%d%d" , &u , &v , &c ); int ans = get ( u , v ); if ( ans < 0 ) ans = 0; printf ( "%d\n" , ans ); change ( u , v , c ); } }}
0 0
- hdu 5052 树链剖分+线段树+区间合并
- hdu 3308 线段树+区间合并
- hdu 3911 线段树+区间合并
- HYSBZ 2243 染色(树链剖分+线段树区间合并)
- hdu 3397(线段树区间合并)
- HDU 3308 线段树+区间合并
- hdu 3308 LCIS 线段树 区间合并
- hdu 3308LCIS 线段树 区间合并
- [HDU 3308]LCIS[线段树][区间合并]
- hdu 3308 线段树区间合并
- hdu 3308 线段树区间合并
- hdu 3911 线段树基本功 区间合并
- hdu 3308 LCIS(线段树区间合并)
- hdu 3308 线段树+区间合并
- HDU-3667 Hetol 线段树 区间合并
- hdu 1806线段树 区间合并
- hdu 1540 线段树区间合并
- HDU 3911 线段树区间合并
- 【Cocos2d-x游戏引擎开发笔记(11)】粒子系统----实现下雪效果
- 六、开发前的准备工作
- HTML5表单提交和PHP环境搭建
- hadoop伪分布式下 无法启动datanode的原因
- Eclipse下的SWT的OpenGL开发(实例及源码)RCP旋转的彩色三棱锥
- hdu 5052 树链剖分+线段树+区间合并
- Linux C++开发环境搭建
- Cocos2d-JS开发中的一些小技巧
- C++学习:vector用法
- 手工释放linux内存——/proc/sys/vm/drop_cache
- C语言课设之 银行管理系统
- Collections.sort()的分析
- I/O model
- LeetCode:Rotate List