【Hdu】6162 Ch’s gift

真的这题名字里面就蕴含了对它的嘲讽:“62”,经典数位Dp题中的所谓的low

一开始准备写正解的,想了好久想到了链剖套主席树,然后,拍链剖和主席树一次性对了,试了试样例,调了调查询操作,过了样例正准备交,以为自己会很快地A掉,毕竟是O(nloglog)的复杂度,但是居然T掉了,真的给写了接近200行的我当头一棒,上网搜题解对拍自己造的随机数据,笔记本没有Vim只能自己找不同,发现200000行数据前面100行全对的,然后我就很懵逼了,然后听说网上的题解有暴力跳过了的,然后改了小部分(呵呵就是把主席树那70多行还有链查询10行删了真少啊)就秒A了

出题人你良心不会痛吗,转门卡死正解,放过暴力

可能是我主席树写的太烂了

其实很简单的一道题跪了一个晚上,题解也不想写了就是一个简单的区间查询值域线段树上的 [ a , b ] 的和改一下线段树结点维护的值就好了记得要开long long不然会炸,暴力利用了随机水数据的期望树高logn就暴力向上跳知道跳到lca为止我告诉你lca都不用求两个点先跳到同一深度然后一起暴力往上跳边跳边判断md代码奇短也奇水无比真的让我无话可说……

TLE的主席树代码:

(我告诉你萌我从来没有如此认真的调试过一道不是考试题的题……

#include <bits/stdc++.h>

#define  RG  register

const  int  N = 100500 + 5 ;

int  head [ N << 1 ] , nxt [ N << 1 ] , to [ N << 1 ] , cn ;
int  top [ N ] , dep [ N ] , out [ N ] , son [ N ] , siz [ N ] , seq [ N ] , fa [ N ] , in [ N ] , idc ;
int  dot [ N ] , pri [ N ] , num ;
int  n , m , s , t , a , b , x , y ;

// line split //

void  create ( int  u , int  v ) {
    cn ++ ;
    to [ cn ] = v ;
    nxt [ cn ] = head [ u ] ;
    head [ u ] = cn ;
}

void  dfs1 ( int  u , int  f ) {
    int  v ;
    siz [ u ] = 1 ;
    for ( RG  int  i = head [ u ] ; i ; i = nxt [ i ] ) {
        v = to [ i ] ;
        if ( v == f )  continue ;
        dep [ v ] = dep [ u ] + 1 ;
        fa [ v ] = u ;
        dfs1 ( v , u ) ;
        siz [ u ] += siz [ v ] ;
        if ( siz [ v ] > siz [ son [ u ] ] )
            son [ u ] = v ;
    }
}

void  dfs2 ( int  u , int  tp ) {
    int  v ;
    seq [ ++ idc ] = u ;
    in [ u ] = idc ;
    top [ u ] = tp ;
    if ( son [ u ] )  dfs2 ( son [ u ] , tp ) ; 
    for ( RG  int  i = head [ u ] ; i ; i = nxt [ i ] ) {
        v = to [ i ] ;
        if ( v == fa [ u ]  ||  v == son [ u ] )  continue ;
        dfs2 ( v , v ) ;
    }
    out [ u ] = idc ;
}
/*
int  LCA ( int  u , int  v ) {
    while ( top [ u ] != top [ v ] ) {
        if ( dep [ top [ u ] ] < dep [ top [ v ] ] )  u ^= v ^= u ^= v ;
        u = fa [ top [ u ] ] ;
    }
    return  dep [ u ] < dep [ v ] ? u : v ;
}
*/
/ Node & segment ///

struct  Node {
    Node  * ls , * rs ;
    long long  val , cnt ;
    void  update ( ) ;
}
pool [ N * 32 ] , * tail = pool , * zero = ++ tail , * root [ N ] ;

void  Node  :: update ( ) {
    val = 0 ;
    if ( ls != zero )  val += ls -> cnt * ls -> val ;
    if ( rs != zero )  val += rs -> cnt * rs -> val ;
}

Node  * build ( int  l , int  r ) {
    Node  * nd = ++ tail ;
    if ( l == r ) {
        nd -> ls = nd -> rs = zero ;
        nd -> val = nd -> cnt = 0 ;
        return  nd ;
    }
    int  mid = l + r >> 1 ;
    nd -> cnt = 0 ;
    nd -> ls = build ( l , mid ) ;
    nd -> rs = build ( mid + 1 , r ) ;
    nd -> update ( ) ;
    return  nd ;
}

Node  * insert ( Node  * nd , int  l , int  r , int  pos ) {
    Node  * nnd = ++ tail ;
    if ( l == r ) {
        nnd -> ls = nnd -> rs = zero ;
        nnd -> cnt = nd -> cnt + 1 ;
        nnd -> val = 1ll * dot [ l ] ;
        return  nnd ;
    }
    int  mid = l + r >> 1 ;
    if ( pos <= mid ) {
        nnd -> rs = nd -> rs ; nnd -> cnt = 1 ;
        nnd -> ls = insert ( nd -> ls , l , mid , pos ) ;
    }
    else {
        nnd -> rs = insert ( nd -> rs , mid + 1 , r , pos ) ;
        nnd -> ls = nd -> ls ; nnd -> cnt = 1 ;
    }
    nnd -> update ( ) ;
    return  nnd ;
}

long long  query ( Node  * lnd , Node  * rnd , int  l , int  r , int  L , int  R ) {
    if ( L <= l  &&  r <= R )  return  rnd -> val * rnd -> cnt - lnd -> val * lnd -> cnt ;
    int  mid = l + r >> 1 ;
    long long  sum = 0 ;
    if ( L <= mid )  sum += query ( lnd -> ls , rnd -> ls , l , mid , L , R ) ;
    if ( R > mid )  sum += query ( lnd -> rs , rnd -> rs , mid + 1 , r , L , R ) ;
    return  sum ;
}

 debug /
/*
void  print_Tree ( Node  * nd ) {
    if ( nd == zero )  return  ;
    printf ( "val : %d     cnt : %d\n" , nd -> val , nd -> cnt ) ;
    print_Tree ( nd -> ls ) ;
    print_Tree ( nd -> rs ) ;
}
*/
 query /

long long  query_ans ( int  u , int  v , int  a , int  b ) {
    long long  sum = 0 ;
    while ( top [ u ] != top [ v ] ) {
        if ( dep [ top [ u ] ] < dep [ top [ v ] ] )  u ^= v ^= u ^= v ;
        sum += query ( root [ in [ top [ u ] ] - 1 ] , root [ in [ u ] ] , 1 , num , a , b ) ;
        u = fa [ top [ u ] ] ;
    }
    if ( dep [ u ] < dep [ v ] )  u ^= v ^= u ^= v ;
    sum += query ( root [ in [ v ] - 1 ] , root [ in [ u ] ] , 1 , num , a , b ) ;
    return  sum ;
}

/*
long long  query_ans ( int  u , int  v , int  a , int  b ) {
	if ( in [ u ] < in [ v ] )  v ^= u ^= v ^= u ;
    return  query ( root [ in [ v ] - 1 ] , root [ in [ u ] ] , 1 , num , a , b ) ;
}*/

 init //

void  init ( ) {
    cn = idc = 0 ; tail = pool ;
    memset ( head , 0 , sizeof ( head ) ) ;
    memset ( top , 0 , sizeof ( top ) ) ;
    memset ( son , 0 , sizeof ( son ) ) ;
    memset ( fa , 0 , sizeof ( fa ) ) ;
}

 main //

int  main ( ) {
    //freopen ( "test.in" , "r" , stdin ) ;
    //freopen ( "mine.out" , "w" , stdout ) ;
    while ( scanf ( "%d%d" , & n , & m ) == 2 ) {
        init ( ) ;
        for ( RG  int  i = 1 ; i <= n ; i ++ )
            scanf ( "%d" , & pri [ i ] ) , dot [ i ] = pri [ i ] ;
        std :: sort ( dot + 1 , dot + n + 1 ) ;
        num = std :: unique ( dot + 1 , dot + n + 1 ) - dot - 1 ;
        for ( RG  int  i = 1 ; i < n ; i ++ ) {
            scanf ( "%d%d" , & x , & y ) ;
            create ( x , y ) ;
            create ( y , x ) ;
        }
        fa [ 1 ] = 1 ;
        dep [ 1 ] = 1 ;
        dfs1 ( 1 , 1 ) ;
        dfs2 ( 1 , 1 ) ;
        root [ 0 ] = build ( 1 , num ) ;
        for ( RG  int  i = 1 ; i <= idc ; i ++ ) {
            int  plc = std :: lower_bound ( dot + 1 , dot + num + 1 , pri [ seq [ i ] ] ) - dot ;
            root [ i ] = insert ( root [ i - 1 ] , 1 , num , plc ) ;
        }
        /*
        printf ( "\n" ) ;
        for ( int  i = 0 ; i <= idc ; i ++ ) {
            printf ( "Root : %d\n" , i ) ;
            print_Tree ( root [ i ] ) ;
            printf ( "\n" ) ;
        }
        */
        for ( RG  int  i = 1 ; i <= m ; i ++ ) {
            scanf ( "%d%d%d%d" , & s , & t , & a , & b ) ;
            printf ( "%lld " , query_ans ( s , t , a , b ) ) ;
        }
        printf ( "\n" ) ;
    }
    return  0 ;
}

AC的垃圾暴力代码:

#include <bits/stdc++.h>

#define  RG  register

const  int  N = 200500 + 5 ;

int  head [ N << 1 ] , nxt [ N << 1 ] , to [ N << 1 ] , cn ;
int  top [ N ] , dep [ N ] , son [ N ] , siz [ N ] , fa [ N ] ;
int  pri [ N ] ;
int  n , m , s , t , a , b , x , y ;

// line split //

void  create ( int  u , int  v ) {
    cn ++ ;
    to [ cn ] = v ;
    nxt [ cn ] = head [ u ] ;
    head [ u ] = cn ;
}

void  dfs1 ( int  u , int  f ) {
    int  v ;
    siz [ u ] = 1 ;
    for ( RG  int  i = head [ u ] ; i ; i = nxt [ i ] ) {
        v = to [ i ] ;
        if ( v == f )  continue ;
        dep [ v ] = dep [ u ] + 1 ;
        fa [ v ] = u ;
        dfs1 ( v , u ) ;
        siz [ u ] += siz [ v ] ;
        if ( siz [ v ] > siz [ son [ u ] ] )
            son [ u ] = v ;
    }
}

void  dfs2 ( int  u , int  tp ) {
    int  v ;
    top [ u ] = tp ;
    if ( son [ u ] )  dfs2 ( son [ u ] , tp ) ; 
    for ( RG  int  i = head [ u ] ; i ; i = nxt [ i ] ) {
        v = to [ i ] ;
        if ( v == fa [ u ]  ||  v == son [ u ] )  continue ;
        dfs2 ( v , v ) ;
    }
}

int  LCA ( int  u , int  v ) {
    while ( top [ u ] != top [ v ] ) {
        if ( dep [ top [ u ] ] < dep [ top [ v ] ] )  u ^= v ^= u ^= v ;
        u = fa [ top [ u ] ] ;
    }
    return  dep [ u ] < dep [ v ] ? u : v ;
}

 query /

long long  query_ans ( int  u , int  v , int  a , int  b ) {
    long long  sum = 0 ;
    int  lca = LCA ( u , v ) ;
    while ( u != lca ) {
    	if ( pri [ u ] >= a  &&  pri [ u ] <= b )  sum += 1ll * pri [ u ] ;
		u = fa [ u ] ;
    }
    if ( pri [ u ] >= a  &&  pri [ u ] <= b )  sum += 1ll * pri [ lca ] ;
    while ( v != lca ) {
    	if ( pri [ v ] >= a  &&  pri [ v ] <= b )  sum += 1ll * pri [ v ] ;
		v = fa [ v ] ;
    }
    return  sum ;
}

 init //

void  init ( ) {
    cn = 0 ;
    memset ( head , 0 , sizeof ( head ) ) ;
    memset ( top , 0 , sizeof ( top ) ) ;
    memset ( son , 0 , sizeof ( son ) ) ;
    memset ( fa , 0 , sizeof ( fa ) ) ;
}

 main //

int  main ( ) {
    freopen ( "test.in" , "r" , stdin ) ;
    while ( scanf ( "%d%d" , & n , & m ) == 2 ) {
        init ( ) ;
        for ( RG  int  i = 1 ; i <= n ; i ++ )
            scanf ( "%d" , & pri [ i ] ) ;
        for ( RG  int  i = 1 ; i < n ; i ++ ) {
            scanf ( "%d%d" , & x , & y ) ;
            create ( x , y ) ;
            create ( y , x ) ;
        }
        fa [ 1 ] = 1 ;
        dep [ 1 ] = 1 ;
        dfs1 ( 1 , 1 ) ;
        dfs2 ( 1 , 1 ) ;
        scanf ( "%d%d%d%d" , & s , & t , & a , & b ) ;
        printf ( "%lld" , query_ans ( s , t , a , b ) ) ;
        for ( RG  int  i = 2 ; i <= m ; i ++ ) {
            scanf ( "%d%d%d%d" , & s , & t , & a , & b ) ;
            printf ( " %lld" , query_ans ( s , t , a , b ) ) ;
        }
        printf ( "\n" ) ;
    }
    return  0 ;
}

洗洗睡吧Hdu你真的牛逼,Noi2018也能让你打到原题冒泡排序,%%%%%%%%%%%%%%%%%%%

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值