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
原创粉丝点击