您的位置:首页 > 其它

BZOJ-3757 苹果树 LCA 莫队算法 树分块

2017-07-01 20:58 411 查看

大家都很强, 可与之共勉 。

嗯, 有版权, 那你把提交关了呀。 全T全RE几个意思?

所以这是RE的代码 。

3757: 苹果树

Time Limit: 20 Sec Memory Limit: 256 MB

Description

神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个到n之间的正整数来表示一种颜色。树上一共有n个苹果。每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。


有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。

神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?

Input

输入第一行为两个整数n和m,分别代表树上苹果的个数和前来膜拜的人数。

接下来的一行包含n个数,第i个数代表编号为i的苹果的颜色Coli。

接下来有n行,每行包含两个数x和y,代表有一根树枝连接了苹果x和y(或者根和一个苹果)。

接下来有m行,每行包含四个整数u、v、a和b,代表这个人要数苹果u到苹果v的颜色种数,同时这个人认为颜色a就是颜色b。如果a=b=0,则代表这个人没有患色盲症。

Output

输出一共m行,每行仅包含一个整数,代表这个人应该数出的颜色种数。

Sample Input

5 3

1 1 3 3 2

0 1

1 2

1 3

2 4

3 5

1 4 0 0

1 4 1 3

1 4 1 2

Sample Output

2

1

2

HINT

0<=x,y,a,b<=N

N<=50000

1<=U,V,Coli<=N

M<=100000

此题存在版权,故不再支持提交,保留在此只供大家参考题面! 望见谅!

Source

# define By_Lazer int main ( ) {  return 0 ;  }

// # define Local

# include <cmath>
# include <cctype>
# include <cstdio>
# include <algorithm>

const size_t str = 1 << 16 ;

char buf[str], *ss, *tt ;

inline char pick ( )  {
return ( ss == tt ) ? ( tt = buf + fread ( ss = buf, 1, str , stdin ), *ss ++ ) : ( *ss ++ ) ;
}

inline int read ( )  {
static char ch;
static int x ;
while ( !isdigit ( ch = pick ( ) ) );
for ( x = -48 + ch ; isdigit ( ch = pick ( ) ) ; ( x *= 10 ) += ch - 48 );
return x ;
}

const int N = 50005 ;
const int M = 100005 ;

int n, m ;

struct edge  {
int to, nxt ;
edge ( )  {  }
edge ( int to, int nxt ) : to ( to ), nxt ( nxt ) {   }
} g [ N << 1 ];

int ne = 1, head
;

inline void AddDe ( int u, int v ) {  g [ ++ ne ] = edge ( v, head[u] ) ; head[u] = ne ; g [ ++ ne ] = edge ( u, head[v] ) ; head[v] = ne ; }

struct node  {
int col, idx ;
} aa
;

int sq ;

int clock ;
int P ;
int anc
[17] ;
int stack
, pos
, top, cnt ;

int dep
;

void Dfs ( int u )  {
aa [u].idx = ++ clock ;
int cur = top ;
for ( int i = head[u] ; i ; i = g [i].nxt )  {
int v = g [i].to ;
if ( v ^ anc [u] [0]  )  {
anc [v] [0] = u ;
dep [v] = dep [u] + 1 ;
Dfs ( v ) ;
if ( top - cur >= sq )  {
++ cnt ;
while ( top ^ cur )
pos [ stack [top --] ] = cnt ;
}
}
}
stack [++ top] = u ;
}

inline void Lca_Init ( )  {
for ( int j = 1 ; j <= P ; ++ j )
for ( int i = 1 ; i <= n ; ++ i )
anc [i] [j] = anc [anc [i] [j - 1]] [j - 1] ;
}

inline int Lca ( int u, int v )  {
if ( dep [u] < dep [v] )  u ^= v ^= u ^= v ;
int t = dep [u] - dep [v] ;
for ( int p = 0 ; p <= P ; ++ p )
if ( t & ( 1 << p ) )  u = anc [u] [p] ;
if ( u == v )  return u ;
for ( int p = P ; anc [u] [0] ^ anc [v] [0]; -- p )
if ( anc [u] [p] ^ anc [v] [p] )
u = anc [u] [p], v = anc [v] [p] ;
return anc [u] [0] ;
}

struct Que  {
int u, v, a, b, id ;
inline short operator < ( const Que& rhs ) const  {
if ( pos [u] < pos [rhs.u] )  return aa [v].idx < aa [rhs.v].idx;
return pos [u] < pos [rhs.u] ;
}
} q [M];

int ans ;
int answer
;
int c
;
short vis
;

inline void reverse ( int node )  {
if ( vis [node] )  {
vis [node] = 0 ;
-- c [aa [node].col] ;
if ( c [aa [node].col] == 0 )  -- ans ;
}  else  {
vis [node] = 1 ;
++ c [aa [node].col] ;
if ( c [aa [node].col] == 1 )  ++ ans ;
}
}

inline void Do ( int u, int v )  {
while ( u ^ v )  {
if ( dep [u] > dep [v] ) reverse ( u ), u = anc [u] [0] ;
else reverse ( v ), v = anc [v] [0] ;
}
}

class Main  {
public :
Main ( )  {
# ifdef Local
freopen ( "in.txt", "r", stdin ) ;
freopen ( "out.txt", "w", stdout ) ;
# endif
n = read ( ), m = read ( ) ;

P = 1 ;
while ( 1 << ( P + 1 ) <= n )  ++ P ;
for ( int i = 1 ; i <= n ; ++ i )  aa [i].col = read ( ) ;

int root ;
for ( int i = 1 ; i <= n ; ++ i )  {
static int u, v ;
u = read ( ), v = read ( ) ;
if ( !u ) root = v ;
else if ( !v ) root = u ;
else AddDe ( u, v ) ;

}
sq = sqrt ( n ) ;
Dfs ( root ) ;
++ cnt ;
while ( top )  pos [ stack [ top -- ] ] = cnt ;
Lca_Init ( ) ;
for ( int i = 1 ; i <= m ; ++ i )  {
q [i].u = read ( ), q [i].v = read ( ), q [i].a = read ( ), q [i].b = read ( ) , q [i].id = i ;
if ( aa [q [i].u].idx > aa [q [i].v].idx )  q [i].u ^= q [i].v ^= q [i].u ^= q [i].v ;
}
std :: sort ( q + 1, q + 1 + m ) ;
int lca = Lca ( q [1].u, q [1].v ) ;
Do ( q [1].u, q [1].v ) ;
reverse ( lca ) ;
answer [q [1].id] = ans ;
if ( c [q [1].a] && c [q [1].b] && ( q [1].a ^ q [1].b ) )  -- answer [q [1].id] ;
for ( int i = 2 ; i <= m ; ++ i )  {
Do ( q[i - 1].u, q[i].u ) ;
Do ( q[i - 1].v, q[i].v ) ;
lca = Lca ( q [i].u, q [i].v ) ;
reverse ( lca ) ;
answer [q [i].id] = ans ;
if ( c [q [i].a] && c [q [i].b] && ( q [i].a ^ q [i].b ) )  -- answer [q [i].id] ;
reverse ( lca ) ;
}
for ( int i = 1 ; i <= m ; ++ i )
printf ( "%d\n", answer [i] ) ;
}
} Z ;

By_Lazer
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: