LCT...略麻烦...

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

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
  
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
  
using namespace std;
 
const int maxn = 100000 + 5;
const int maxnode = maxn + 100;
const int MOD = 51061;
const int maxedge = maxn << 1;
 
#define mod( x ) ( ( x ) %= MOD )
 
int n;
 
struct edge {
int to;
edge* next;
};
 
edge* head[ maxn ];
edge EDGE[ maxedge ];
edge* e_pt;
 
void add( int u , int v ) {
e_pt -> to = v;
e_pt -> next = head[ u ];
head[ u ] = e_pt++;
}
 
#define add_edge( u , v ) add( u , v ) , add( v , u )
 
void edge_init() {
e_pt = EDGE;
clr( head , 0 );
}
 
struct Node *pt , *null;
 
struct Node {
Node *ch[ 2 ] , *p , *fa;
int add , mul , sum , v , s;
bool isRoot , rev;
Node() : v( 1 ) , add( 0 ) , mul( 1 ) , sum( 1 ) , s( 1 ) {
ch[ 0 ] = ch[ 1 ] = p = fa = null;
isRoot = true;
rev = false;
}
inline void setc( Node* c , int d ) {
ch[ d ] = c;
c -> p = this;
}
inline bool d() {
return this == p -> ch[ 1 ];
}
inline void relax() {
if( rev ) {
rev = false;
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Rev();
}
if( mul != 1 ) {
rep( i , 2 ) if( ch[ i ] != null ) 
   ch[ i ] -> Mul( mul );
mul = 1;
}
if( add ) {
rep( i , 2 ) if( ch[ i ] != null )
   ch[ i ] -> Add( add );
add = 0;
}
}
inline void upd() {
s = ch[ 0 ] -> s + ch[ 1 ] -> s + 1;
mod( sum = ch[ 0 ] -> sum + v + ch[ 1 ] -> sum );
}
inline void Rev() {
rev ^= 1;
swap( ch[ 0 ] , ch[ 1 ] );
}
inline void Add( int ad ) {
mod( add += ad );
mod( sum += 1LL * ad * s % MOD );
mod( v += ad );
}
inline void Mul( int mu ) {
add = 1LL * add * mu % MOD;
mul = 1LL * mul * mu % MOD;
sum = 1LL * sum * mu % MOD;
v = 1LL * v * mu % MOD;
}
inline void setRoot() {
fa = p;
p = null;
isRoot = true;
}
void* operator new( size_t ) {
return pt++;
}
};
 
Node NODE[ maxnode ];
void rot( Node* t ) {
Node* p = t -> p;
p -> relax();
t -> relax();
int d = t -> d();
p -> p -> setc( t , p -> d() );
p -> setc( t -> ch[ d ^ 1 ] , d );
t -> setc( p , d ^ 1 );
p -> upd();
if( p -> isRoot ) {
p -> isRoot = false;
t -> isRoot = true;
t -> fa = p -> fa;
}
}
 
void splay( Node* t , Node* f = null ) {
static Node* S[ maxn ];
int top = 0;
for( Node* o = t ; o != null ; o = o -> p ) S[ ++top ] = o;
while( top ) S[ top-- ] -> relax();
for( Node* p = t -> p ; p != f ; p = t -> p ) {
if( p -> p != f )
   p -> d() != t -> d() ? rot( t ) : rot( p );
rot( t );
}
t -> upd();
}
 
void access( Node* t ) {
for( Node* o = null ; t != null ; o = t , t = t -> fa ) {
splay( t );
t -> ch[ 1 ] -> setRoot();
t -> setc( o , 1 );
}
}
 
void makeRoot( Node* t ) {
access( t );
splay( t );
t -> Rev();
}
 
Node* findRoot( Node* t ) {
access( t );
splay( t );
for( ; t -> ch[ 0 ] != null ; t = t -> ch[ 0 ] )
   t -> relax();
splay( t );
return t;
}
 
void cut( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( x );
x -> setc( null , 1 );
x -> upd();
y -> p = null;
y -> setRoot();
}
 
void join( Node* x , Node* y ) {
makeRoot( x );
x -> fa = y;
}
 
Node* get( Node* x , Node* y ) {
makeRoot( x );
access( y );
splay( y );
return y;
}
 
void node_init() {
pt = NODE;
null = new( Node );
null -> s = null -> v = null -> sum = 0;
}
 
Node* V[ maxn ];
 
void dfs( int x , int par ) {
for( edge* e = head[ x ] ; e ; e = e -> next ) {
int to = e -> to;
if( to == par ) continue;
dfs( to , x );
V[ to ] -> fa = V[ x ];
}
}
 
void build_tree() {
rep( i , n ) V[ i ] = new( Node );
dfs( 0 , -1 );
}
 
int main() {
freopen( "test.in" , "r" , stdin );
freopen( "test.out" , "w" , stdout );
edge_init();
node_init();
int q , u , v;
cin >> n >> q;
rep( i , n - 1 ) {
scanf( "%d%d" , &u , &v );
u-- , v--;
add_edge( u , v );
}
build_tree();
char op;
while( q-- ) {
scanf( " %c%d%d" , &op , &u , &v );
u-- , v--;
if( op == '-' ) {
cut( V[ u ] , V[ v ] );
scanf( "%d%d" , &u , &v );
u-- , v--;
join( V[ u ] , V[ v ] );
} else if( op == '/' ) {
printf( "%d\n" , get( V[ u ] , V[ v ] ) -> sum );
} else {
int c;
scanf( "%d" , &c );
mod( c );
op != '+' ? get( V[ u ] , V[ v ] ) -> Mul( c ) : get( V[ u ] , V[ v ] ) -> Add( c );
}
}
return 0;
}

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

2631: tree

Time Limit: 30 Sec  Memory Limit: 128 MB
Submit: 2454  Solved: 819
[Submit][Status][Discuss]

Description

 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。

Input

  第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

Output

  对于每个/对应的答案输出一行

Sample Input

3 2
1 2
2 3
* 1 3 4
/ 1 1

Sample Output

4

HINT

数据规模和约定

10%的数据保证,1<=n,q<=2000

另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链

另外35%的数据保证,1<=n,q<=5*10^4,没有-操作

100%的数据保证,1<=n,q<=10^5,0<=c<=10^4

Source

BZOJ 2631: tree( LCT )的更多相关文章

  1. BZOJ 2631: tree [LCT splay区间]

    2631: tree Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 3854  Solved: 1292[Submit][Status][Discus ...

  2. [BZOJ - 2631] tree 【LCT】

    题目链接:BZOJ - 2631 题目分析 LCT,像线段树区间乘,区间加那样打标记. 这道题我调了一下午. 提交之后TLE了,我一直以为是写错了导致了死循环. 于是一直在排查错误.直到.. 直到我看 ...

  3. bzoj 2631: tree 动态树+常数优化

    2631: tree Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 1716  Solved: 576[Submit][Status] Descrip ...

  4. 【BZOJ】2631: tree LCT

    [题意]给定n个点的树,每个点初始权值为1,m次操作:1.x到y的点加值,2.断一条边并连一条边,保证仍是树,3.x到y的点乘值,4.x到y的点权值和取模.n,m<=10^5. [算法]Link ...

  5. BZOJ 2631 tree / Luogu P1501 [国家集训队]Tree II (LCT,多重标记)

    题意 一棵树,有删边加边,有一条链加/乘一个数,有询问一条链的和 分析 LCT,像线段树一样维护两个标记(再加上翻转标记就是三个),维护size,就行了 CODE #include<bits/s ...

  6. BZOJ 2631 tree | Luogu P1501 [国家集训队]Tree II (LCT 多重标记下放)

    链接:https://www.luogu.org/problemnew/show/P1501 题面: 题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: ...

  7. BZOJ 3282: Tree( LCT )

    LCT.. -------------------------------------------------------------------------------- #include<c ...

  8. BZOJ 2631 tree(动态树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2631 [题目大意] 要求支持链修改,链查询,边断开,连接操作 [题解] 链修改分乘和加 ...

  9. BZOJ 2631 tree 动态树(Link-Cut-Tree)

    题目大意:维护一种树形数据结构.支持下面操作: 1.树上两点之间的点权值+k. 2.删除一条边.添加一条边,保证加边之后还是一棵树. 3.树上两点之间点权值*k. 4.询问树上两点时间点的权值和. 思 ...

随机推荐

  1. rsync、ssh备份

    Linux系统需求 为了实现这个备份程序,需要准备一个外部驱动器.您可以将备份写到一个外部USB磁盘,但这样做效率不高.因此,我假设您将备份写到位于网络某处的服务器中.这台服务器要为带有SSH和rsy ...

  2. angulajs 当input使用 bootstrap的email类型时,如果是无效的email格式,则ng-model无效的情况

    当使用bootstrap的如下input时 <input type="email" ng-model="userid"> 如果输入的内容是无效的em ...

  3. php call_user_func和call_user_func_array

    首先要看这个页面关于callable类型:http://www.php.net/manual/zh/language.types.callable.php 自 PHP 5.4 起可用 callable ...

  4. perl5 第三章 操作符

    第三章 操作符 by flamephoenix 一.算术操作符二.整数比较操作符三.字符串比较操作符四.逻辑操作符五.位操作符六.赋值操作符七.自增自减操作符八.字符串联结和重复操作符九.逗号操作符十 ...

  5. cocos2d-x中的尺寸之二

    接下来我们再做些坏事,比如给EGLView设置分辨率,代码如下: pEGLView->setDesignResolutionSize(240, 320, kResolutionExactFit) ...

  6. shell脚本内与mysql交互

    一: mysqlCMD="mysql -h${MYSQL_HOST}  -P${MYSQL_PORT}  -u${MYSQL_USER} -p${MYSQL_PASS}" crea ...

  7. js静态方法和实例方法

    js静态方法 function foo(){} // 声明类 foo.method = function(){} // 方法体 使用:foo.method() js实例方法 function foo( ...

  8. Linq to sql介绍及增、删、改、查

    LinQ是指集成化查询语言,通过映射将数据库内的表名变为C#的类名,将列名作为属性名,将表的关系作为类的成员对象.O--M--R O-Object对象 R-Relation关系 M-Mapping映射 ...

  9. Definitions

    Definitions and ODR Definitions are declarations that fully define the entity introduced by the decl ...

  10. 分布式session

    前端用户请求经过随机分发之后,可能会命中后端任意的Web Server,并且 Web Server 也可能会因为各种不确定的原因宕机.在这种情况下,session 是很难在集群间同步的,而通过将ses ...