真的这题名字里面就蕴含了对它的嘲讽:“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也能让你打到原题冒泡排序,%%%%%%%%%%%%%%%%%%%