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
相关文章推荐
- [BZOJ3757]苹果树(树上莫队+分块)
- bzoj 3757 苹果树(树上莫队算法)
- 树上(带修改)莫队算法-- bzoj4129 && bzoj3757
- 【莫队算法】【权值分块】bzoj2223 [Coci 2009]PATULJCI
- 【树上莫队】bzoj3757 苹果树
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
- bzoj 3236: [Ahoi2013]作业 莫队算法+分块
- BZOJ 3757 苹果树 树上莫队
- BZOJ 3757 苹果树 树上莫队
- bzoj3757 苹果树(路径树上莫队)
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
- BZOJ 3809 Gty的二逼妹子序列 莫队算法+分块
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
- BZOJ 3809 Gty的二逼妹子序列 莫队算法+分块
- 【莫队算法】【权值分块】bzoj3809 Gty的二逼妹子序列
- BZOJ_P3757 苹果树(树上莫队+LCA)
- [BZOJ 3757]苹果树:树上莫队
- 【BZOJ-2453&2120】维护队列&数颜色 分块 + 带修莫队算法
- bzoj 3757: 苹果树(树上莫队)
- 【莫队算法】【权值分块】bzoj3236 [Ahoi2013]作业