说多了都是泪啊...调了这么久..

离线可以搞 , 树链剖分就OK了...

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

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
 
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define Rep( i , n ) for( int i = 1 ; i <= n ; ++i )
#define REP( x ) for( edge* e = head[ x ] ; e ; e = e -> next )
#define mod( x ) ( ( x ) %= MOD )
#define M( l , r ) ( ( l + r ) >> 1 )
#define L( x ) ( ( x ) << 1 )
#define R( x ) ( L( x ) ^ 1 )
 
using namespace std;
 
const int maxn = 50000 + 5;
const int maxnode = 140000;
const int MOD = 201314;
 
int n;
  
struct edge {
int to;
edge* next;
};
 
edge* pt , EDGE[ maxn ];
edge* head[ maxn ];
 
inline void add_edge( int u , int v ) {
pt -> to = v;
pt -> next = head[ u ];
head[ u ] = pt++;
}
 
void edge_init() {
pt = EDGE;
clr( head , 0 );
}
 
 
int top[ maxn ] , fa[ maxn ] , son[ maxn ] , size[ maxn ];
 
void dfs( int x ) {
size[ x ] = 1;
REP( x ) {
int to = e -> to;
dfs( to );
size[ x ] += size[ to ];
if( son[ x ] == -1 || size[ to ] > size[ son[ x ] ] )
   son[ x ] = to;
}
}
 
int id[ maxn ] , id_cnt = 0;
int TOP;
void DFS( int x ) {
id[ x ] = ++id_cnt;
top[ x ] = TOP;
if( son[ x ] != -1 )
   DFS( son[ x ] );
REP( x ) if( e -> to != son[ x ] )
   DFS( TOP = e -> to );
}
 
void DFS_init() {
clr( son , -1 );
dfs( 0 );
DFS( TOP = 0 );
}
 
 
int add[ maxnode ] , sum[ maxnode ];
int L , R , query_ans;
 
inline void maintain( int x , int l , int r ) {
sum[ x ] = add[ x ] * ( r - l + 1 );
if( r > l )
   sum[ x ] += sum[ L( x ) ] + sum[ R( x ) ];
}
 
void update( int x , int l , int r ) {
if( L <= l && r <= R )
   add[ x ]++;
else {
int m = M( l , r );
if( L <= m ) update( L( x ) , l , m );
if( m < R) update( R( x) , m + 1 , r );
}
maintain( x , l , r );
}
inline void Update( int l , int r ) {
L = l , R = r;
update( 1 , 1 , n );
}
 
void query( int x , int l , int r , int Add ) {
if( L <= l && r <= R ) 
   query_ans += sum[ x ] + Add * ( r - l + 1 );
else {
Add += add[ x ];
int m = M( l , r );
if( L <= m ) query( L( x ) , l , m , Add );
if( m < R ) query( R( x ) , m + 1 , r , Add );
}
}
inline int Query( int l , int r ) {
query_ans = 0;
L = l , R = r;
query( 1 , 1 , n , 0 );
return query_ans;
}
 
int Q( int x ) {
int res = 0;
while( top[ x ] != top[ 0 ] ) {
mod( res += Query( id[ top[ x ] ] , id[ x ] ) );
x = fa[ top[ x ] ];
}
return ( res + Query( id[ 0 ] , id[ x ] ) ) % MOD;
}
 
void modify( int x ) {
while( top[ x ] != top[ 0 ] ) {
Update( id[ top[ x ] ] , id[ x ] );
x = fa[ top[ x ] ];
}
Update( id[ 0 ] , id[ x ] );
}
 
 
struct data {
int x , num , s;
bool operator < ( const data &rhs ) const {
return x < rhs.x;
}
};
 
data A[ maxn << 1 ];
int z[ maxn ];
int ans[ maxn ];
 
int read() {
int ans = 0;
char c = getchar();
while( ! isdigit( c ) ) c = getchar();
while( isdigit( c ) ) {
ans = ans * 10 + c - '0';
c = getchar();
}
return ans;
}
 
int main() {
freopen( "test.in" , "r" , stdin );
n = read();
int q = read();
edge_init();
Rep( i , n - 1 ) {
   fa[ i ] = read();
   add_edge( fa[ i ] , i );
}
rep( i , q ) {
data &a = A[ i ] , &b = A[ i + q ];
a.x = read() , b.x = read();
*( z + i ) = read();
a.x--;
a.s = -1 , b.s = 1;
a.num = b.num = i;
}
DFS_init();
clr( sum , 0 );
q <<= 1;
sort( A , A + q );
int cur = 0;
clr( ans , 0 );
for( ; cur < q && A[ cur ].x < 0 ; cur++ );
rep( i , n ) {
modify( i );
for( ; cur < q , A[ cur ].x == i ; cur++ )
   mod( mod( ans[ A[ cur ].num ] += Q( z[ A[ cur ].num ] ) * A[ cur ].s ) += MOD );
}
q >>= 1;
rep( i , q )
   printf( "%d\n" , ans[ i ] );
return 0;
}

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

3626: [LNOI2014]LCA

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 855  Solved: 291
[Submit][Status][Discuss]

Description

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

Input

第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。

Output

输出q行,每行表示一个询问的答案。每个答案对201314取模输出

Sample Input

5 2
0
0
1
1
1 4 3
1 4 2

Sample Output

8
5

HINT

共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

Source

BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  2. BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线

    http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...

  3. bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...

  4. BZOJ 3626 [LNOI2014]LCA ——树链剖分

    思路转化很巧妙. 首先把询问做差分. 然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和. 这样和原问题是等价的,然后树链剖分+线段树就可以做了. #include <map ...

  5. 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)

    题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...

  6. bzoj3626: [LNOI2014]LCA (树链剖分+离线线段树)

    Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. ...

  7. [LNOI2014]LCA 树链剖分 离线 前缀和 思维题

    题目描述:给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. 有q次询问,每 ...

  8. [BZOJ3626] [LNOI2014]LCA(树链剖分)

    [BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...

  9. BZOJ3626[LNOI2014]LCA——树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

随机推荐

  1. C++的常量折叠(三)

    背景知识 在开始之前先说一下符号表,这个编译器中的东西.下面看一下百度百科中的描述: 符号表是一种用于语言翻译器中的数据结构.在符号表中,程序源代码中的每个标识符都和它的声明或使用信息绑定在一起,比如 ...

  2. Snap.svg中transform旋转值的“r+数组”表现形式

    Snap.svg中transform的值还可以写为类似以下这种形式: transform:'r'+[100,[50,50]]; 这种写法的意思是,让元素以(50,50)为旋转中心点,然后旋转100度. ...

  3. php不同版本特性记录

    最近在用php开发时项目中遇到了版本问题,特此记录下php不同版本的一些特性记录,以备忘. 一:php5.3中的新特性 1)开始支持命名空间(Namespace) 2)支持延迟静态绑定(Late St ...

  4. [Windows编程] 使用AttachThreadInput 来捕捉其它窗口的键盘输入

    在一些情况下(比如屏幕软键盘或者输入法程序),自己的窗口没有输入焦点但是想要当前焦点窗口的键盘输入消息,可以使用Win32 API函数AttachThreadInput()来解决这个问题.Attach ...

  5. Pascal向C++的跨越

    最近从pas转向了C++,觉得需要在语言上总结对比一下,以及记录一些注意点,关于STL,还需要之后好好地学习.同时,希望这篇文章对从pas转C++的同学有所帮助. 基本类型 首先是基本类型的比较: P ...

  6. JAVA中List、Map、Set的区别与选用

    类层次关系如下: Collection ├List│├LinkedList│├ArrayList│└Vector│ └Stack└SetMap├Hashtable├HashMap └WeakHashM ...

  7. POJ 2762 Going from u to v or from v to u? (Tarjan) - from lanshui_Yang

    Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has ...

  8. IOS文件沙盒

    在进行IPhone开发的时候,常常需要将简单的数据保存到文件中,以便下次再重新打开的时候能够读取文件中保存的数据. 下面就来做一个简单的demo: 步骤: 1.创建一个SingleView项目,带有x ...

  9. Java之SPI机制

    之前开阿里的HSF框架,里面用到了Java的SPI机制,今天闲暇的时候去了解了一下,通过写博客来记录一下 SPI的全名为Service Provider Interface,我对于该机制的理解是为接口 ...

  10. Java排序之排序大综合

    一.最近写了一些排序,于是和和大家分享一下:(默认都是从小到大排序) 二.冒泡排序 1.什么是冒泡排序:原理是临近的两个数比较大小,将较大的数往后移,这样遍历一趟数组以后,最大的数就排在的最后面(时间 ...