spoj 375 query on a tree LCT
这道题是树链剖分的裸题,正在学LCT,用LCT写了,发现LCT代码比树链剖分还短点(但我的LCT跑极限数据用的时间大概是kuangbin大神的树链剖分的1.6倍,所以在spoj上是850ms卡过的)。
收获:
1、边转换成点(即若存在边(u,v),则新加一个点z代表边,将z连接u和v,z的点权就是(u,v)的边权,非边点的权设为-oo),然后对边权的统计就变成了对点权的统计(这是LCT中处理边信息的通法之一)。
2、若要连接两个点u,v,先让它们分别称为根,然后将其中一个的path-parent设为另一个。
3、若要查找(u,v)的边点,运用“夹逼法”,先让两个点在一条重链上(即同一棵splay树),再splay(u,0)和splay(v,u),这样v的一个子树就是边点(具体来说,可以先让u成为根,再access(v),splay(u,0),splay(v,u),此时v的左儿子必定是边点)
#include <cstdio>
#include <iostream>
#define maxn 20010
#define oo 0x3f3f3f3f
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std; struct LCT {
int pnt[maxn], pre[maxn], son[maxn][], val[maxn], mxv[maxn], ntot;
bool tag[maxn]; inline void update( int nd ) {
mxv[nd] = max( val[nd], max( mxv[son[nd][]], mxv[son[nd][]] ) );
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d]; son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][] ] = s;
else pnt[s] = pnt[nd]; pre[nd] = s;
pre[s] = p;
if( ss ) pre[ss] = nd; update( nd );
update( s );
}
inline void pushdown( int nd ) {
if( tag[nd] ) {
int &ls = son[nd][], &rs = son[nd][];
swap( ls, rs );
tag[ls] ^= ;
tag[rs] ^= ;
tag[nd] = ;
}
}
void splay( int nd, int top= ) {
static int stk[maxn], spt;
int u = nd;
for( spt=; u; u=pre[u] )
stk[spt++] = u;
while( spt-- )
pushdown( stk[spt] );
while( pre[nd]!=top ) {
int p = pre[nd];
int nl = nd==son[p][];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp = pre[p];
int pl = p==son[pp][];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
void init( int n ) {
for( int i=; i<=n; i++ ) {
pre[i] = pnt[i] = son[i][] = son[i][] = tag[i] = ;
mxv[i] = val[i] = -oo;
}
}
void access( int nd ) {
int u = nd;
int v = ;
while( u ) {
splay( u );
int s = son[u][];
pre[s] = ;
pnt[s] = u;
pre[v] = u;
son[u][] = v;
v = u;
u = pnt[u];
}
splay( nd );
}
void makeroot( int nd ) {
access( nd );
tag[nd] ^= ;
}
void link( int u, int v ) {
makeroot(u);
makeroot(v);
pnt[u] = v;
}
void modify( int e, int w ) {
splay(e);
val[e] = w;
update( e );
}
int query( int u, int v ) {
makeroot(u);
access(v);
return max(val[v],mxv[son[v][]]);
}
}; int n;
LCT LT; int main() {
int T;
scanf( "%d", &T );
while( T-- ) {
scanf( "%d", &n );
LT.init(n+n-);
for( int i=,u,v,w; i<n; i++ ) {
scanf( "%d%d%d", &u, &v, &w );
LT.modify( n+i, w );
LT.link( u, n+i );
LT.link( v, n+i );
}
while() {
char ch[];
scanf( "%s", ch );
if( ch[]=='Q' ) {
int u, v;
scanf( "%d%d", &u, &v );
printf( "%d\n", LT.query(u,v) );
} else if( ch[]=='C' ) {
int e, w;
scanf( "%d%d", &e, &w );
LT.modify( n+e, w );
} else break;
}
}
}
spoj 375 query on a tree LCT的更多相关文章
- SPOJ 375. Query on a tree (动态树)
375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...
- SPOJ 375. Query on a tree (树链剖分)
Query on a tree Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Ori ...
- 动态树(Link Cut Tree) :SPOJ 375 Query on a tree
QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...
- spoj 375 Query on a tree(树链剖分,线段树)
Query on a tree Time Limit: 851MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Sub ...
- spoj 375 Query on a tree (树链剖分)
Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...
- SPOJ 375 Query on a tree 树链剖分模板
第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...
- SPOJ 375 Query on a tree(树链剖分)(QTREE)
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- SPOJ 375 Query on a tree【树链剖分】
题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值 思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了 #inc ...
- SPOJ 375 Query on a tree(树链剖分)
https://vjudge.net/problem/SPOJ-QTREE 题意: 给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值. 思路: 树链剖 ...
随机推荐
- NYOJ 257 郁闷的C小加(一) (字符串处理)
题目链接 描述 我们熟悉的表达式如a+b.a+b(c+d)等都属于中缀表达式.中缀表达式就是(对于双目运算符来说)操作符在两个操作数中间:num1 operand num2.同理,后缀表达式就是操作符 ...
- lintcode 66.67.68 二叉树遍历(前序、中序、后序)
AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int val; * public TreeNode le ...
- flask基础之安装和使用入门(一)
前言 Flask框架作为一个python极简化的web框架,它不像Django那样的重型,非常适合快速开发一些小型的应用.本人用flask开发了几个项目之后,慢慢研究flask底层的一些原理,开始一步 ...
- {%csrf_token%}的作用
<form> {%csrf_token%} </form> 在django中我们需要在templates的form中加入{%csrf_token%}这串内容,它的作用是当我们g ...
- linux -j 4
把源码编译成可执行的二进制文件, 4为服务器内核数
- linux自动获得mac地址,修改网络配置
1.修改网络配置,自动获得mac地址 删除 /etc/udev/rules.d/70-persistent-net.rules 文件 删除 /etc/sysconfig/network-scripts ...
- 产生随机数 random
int rand(void); 返回 0 ------- RAND_MAX 之间的一个 int 类型整数,该函数为非线程安全函数.并且生成随机数的性能不是很好,已经不推荐使用. void ...
- MySQL-开发规范升级版
一.基础规范 表存储引擎必须使用InnoDB 表字符集默认使用utf8,必要时候使用utf8mb4 解读: (1)通用,无乱码风险,汉字3字节,英文1字节 (2)utf8mb4是utf8的超集,有 ...
- Java web项目中新建maven项目出现的问题
1.首先新建maven项目,新建Maven时出现了版本问题,报错 第一个错误:jdk版本与project facets不匹配(大概是这样,忘记截图了),那么解决办法是: 在项目右击--->Pro ...
- live555例子程序编译连接时发现函数未定义问题
1 调整连接库的顺序. 2 更新头文件与所用的库一致