BZOJ 1103: [POI2007]大都市meg( 树链剖分 )

早上数学考挂了...欲哭无泪啊下午去写半个小时政治然后就又可以来刷题了..

树链剖分 , 为什么跑得这么慢...

---------------------------------------------------------------------

#include<cstdio>

#include<algorithm>

#include<iostream>

#include<cstring>

#define rep( i , n ) for( int i = 0 ; i < n ; ++i )

#define clr( x , c ) memset( x , c , sizeof( x ) )

#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )

using namespace std;

const int maxn = 250000 + 5;

const int maxnode = 525000;

int n;

struct edge {

int to;

edge* next;

};

edge* pt , E[ maxn << 1 ];

edge* head[ maxn ];

void init() {

pt = E;

clr( head , 0 );

}

inline void Add( int u , int v ) {

pt -> to = v;

pt -> next = head[ u ];

head[ u ] = pt++;

}

#define add_edge( u , v ) Add( u , v ) , Add( v , u )

int top[ maxn ] , fa[ maxn ] , size[ maxn ] , dep[ maxn ] , son[ maxn ];

int id[ maxn ] , id_cnt = 0 , TOP;

int dfs( int x ) {

size[ x ] = 1;

son[ x ] = -1;

REP( x ) {

int to = e -> to;

if( to == fa[ x ] ) continue;

fa[ to ] = x;

dep[ to ] = dep[ x ] + 1;

dfs( to );

size[ x ] += size[ to ];

if( son[ x ] == -1 || size[ son[ x ] ] < size[ to ] )

son[ x ] = to;

}

}

void DFS( int x ) {

id[ x ] = ++id_cnt;

top[ x ] = TOP;

if( son[ x ] != -1 ) DFS( son[ x ] );

REP( x ) {

int to = e -> to;

if( to == fa[ x ] || to == son[ x ] ) continue;

DFS( TOP = to );

}

}

void DFS_init() {

dfs( dep[ 0 ] = 0 );

DFS( TOP = 0 );

}

int sum[ maxnode ] , L , R;

bool tag[ maxnode ];

#define L( x ) ( ( x ) << 1 )

#define R( x ) ( L( x ) ^ 1 )

#define M( l , r ) ( ( l + r ) >> 1 )

void ADD( int x , int l , int r ) {

if( tag[ x ] ) return;

if( L <= l && r <= R ) {

tag[ x ] = true;

sum[ x ] = 0;

} else {

int m = M( l , r );

if( L <= m ) ADD( L( x ) , l , m );

if( m < R ) ADD( R( x ) , m + 1 , r );

sum[ x ] = sum[ L( x ) ] + sum[ R( x ) ];

}

}

int query( int x , int l , int r ) {

if( L <= l && r <= R )

return sum[ x ];

int m = M( l , r );

return ( L <= m ? query( L( x ) , l , m ) : 0 ) + ( m < R ? query( R( x ) , m + 1 , r ) : 0 );

}

void modify( int x , int y ) {

while( top[ x ] != top[ y ] ) {

if( dep[ top[ x ] ] < dep[ top[ y ] ] ) swap( x , y );

L = id[ top[ x ] ] , R = id[ x ];

ADD( 1 , 1 , n );

x = fa[ top[ x ] ];

}

if( x == y ) return;

if( dep[ x ] < dep[ y ] ) swap( x , y );

L = id[ y ] + 1 , R = id[ x ];

ADD( 1 , 1 , n );

}

int Q( int x , int y ) {

int ans = 0;

while( top[ x ] != top[ y ] ) {

if( dep[ top[ x ] ] < dep[ top[ y ] ] ) swap( x , y );

L = id[ top[ x ] ] , R = id[ x ];

ans += query( 1 , 1 , n );

x = fa[ top[ x ] ];

}

if( x == y ) return ans;

if( dep[ x ] < dep[ y ] ) swap( x , y );

L = id[ y ] + 1 , R = id[ x ];

return ans + query( 1 , 1 , n );

}

void build( int x , int l , int r ) {

sum[ x ] = r - l + 1;

if( r > l ) {

int m = M( l , r );

build( L( x ) , l , m );

build( R( x ) , m + 1 , r );

}

}

int main() {

// freopen( "test.in" , "r" , stdin );

init();

cin >> n;

rep( i , n - 1 ) {

int u , v;

scanf( "%d%d" , &u , &v );

--u , --v;

add_edge( u , v );

}

DFS_init();

clr( tag , 0 );

build( 1 , 1 , n );

int m;

cin >> m;

m += n;

char c;

while( --m ) {

int u , v;

scanf( " %c" , &c );

scanf( "%d" , &u );

u--;

if( c == ‘W‘ ) {

printf( "%d\n" , Q( 0 , u ) );

} else {

scanf( "%d" , &v );

--v;

modify( u , v );

}

}

return 0;

}

--------------------------------------------------------------------

1103: [POI2007]大都市meg

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1334  Solved: 690
[Submit][Status][Discuss]

Description

在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了。不过,她经常回忆起以前在乡间漫步的情景。昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双向的土路。从每个村庄都恰好有一条路径到达村庄1(即比特堡)。并且,对于每个村庄,它到比特堡的路径恰好只经过编号比它的编号小的村庄。另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇。在这个未开化的地方,从来没有过高架桥和地下铁道。随着时间的推移,越来越多的土路被改造成了公路。至今,Blue Mary还清晰地记得最后一条土路被改造为公路的情景。现在,这里已经没有土路了——所有的路都成为了公路,而昔日的村庄已经变成了一个大都市。 Blue Mary想起了在改造期间她送信的经历。她从比特堡出发,需要去某个村庄,并且在两次送信经历的间隔期间,有某些土路被改造成了公路.现在Blue Mary需要你的帮助:计算出每次送信她需要走过的土路数目。(对于公路,她可以骑摩托车;而对于土路,她就只好推车了。)

Input

第一行是一个数n(1 < = n < = 2 50000). 
以下n-1行,每行两个整数a,b(1 < =  a以下一行包含一个整数m(1 < = m < = 2 50000),表示Blue Mary曾经在改造期间送过m次信。 
以下n+m-1行,每行有两种格式的若干信息,表示按时间先后发生过的n+m-1次事件: 
若这行为 A a b(a若这行为 W a, 则表示Blue Mary曾经从比特堡送信到村庄a。

Output

有m行,每行包含一个整数,表示对应的某次送信时经过的土路数目。

Sample Input

5
1 2
1 3
1 4
4 5
4
W 5
A 1 4
W 5
A 4 5
W 5
W 2
A 1 2
A 1 3

Sample Output

2
1
0
1

HINT

Source

时间: 2024-09-29 01:23:45

BZOJ 1103: [POI2007]大都市meg( 树链剖分 )的相关文章

数据结构(线段树):BZOJ 1103 [POI2007]大都市meg

1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1791  Solved: 925[Submit][Status][Discuss] Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双 向的土路.从每个村庄都恰好有一条路径

bzoj 1103: [POI2007]大都市meg

1103: [POI2007]大都市meg Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了. 不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双 向的土路.从每个村庄都恰好有一条路径到达村庄1(即比特堡).并且,对于每个村庄,它到比特堡的路径恰好 只经过编号比它的编号小的村庄.另外,对于所有道路而言,它们都不在除村庄以外的其他地点相遇.在这个未开 化的地方,从来

[bzoj1103][POI2007]大都市meg(树状数组+dfs序)

1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2031  Solved: 1069[Submit][Status][Discuss] Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n的n个小村庄,某些村庄之间有一些双向的土路.从每个村庄都恰好有一条路径到

BZOJ 2243:染色(树链剖分+区间合并线段树)

[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”.“222”和“1”.请你写一个程序依次完成这m个操作.Input第一行包含2个整数n和m,分别表示节点数和操作数:第二行包含n个正整数表示n个节点的初始颜色下面 行每行包含两个整数x和y,表示x和y之间有一条无向边.下面 行每行描述一个操作:“C

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总

BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. 时间复杂度O(N*log^3(N)) ---------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<

BZOJ 3626 LNOI 2014 LCA 树链剖分

题目大意:给出一棵树,有n个问题,询问在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和. 思路:不会,然后看了题解,之后发现自己智商严重不足. 看到数据范围就知道一定要离线处理,就这个离线处理我估计以我的智商不看题解是肯定想不出来的.. 考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案.观察到,深度其实就是上面有几个已标记了的点(包括自身).所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r

bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Status][Discuss] Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a . 操作 3 :询问某个节点 x 到根的路径中所有

BZOJ 1787: [Ahoi2008]Meet 紧急集合( 树链剖分 )

这道题用 LCA 就可以水过去 , 但是我太弱了 QAQ 倍增写LCA总是写残...于是就写了树链剖分... 其实也不难写 , 线段树也不用用到 , 自己YY一下然后搞一搞就过了...速度还挺快的好像= = #9 ---------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algori