这道题是树链剖分的裸题,正在学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的更多相关文章

  1. SPOJ 375. Query on a tree (动态树)

    375. Query on a tree Problem code: QTREE You are given a tree (an acyclic undirected connected graph ...

  2. SPOJ 375. Query on a tree (树链剖分)

    Query on a tree Time Limit: 5000ms Memory Limit: 262144KB   This problem will be judged on SPOJ. Ori ...

  3. 动态树(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) ...

  4. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

  5. 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 ...

  6. SPOJ 375 Query on a tree 树链剖分模板

    第一次写树剖~ #include<iostream> #include<cstring> #include<cstdio> #define L(u) u<&l ...

  7. 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, ...

  8. SPOJ 375 Query on a tree【树链剖分】

    题目大意:给你一棵树,有两个操作1.修改一条边的值,2.询问从x到y路径上边的最大值 思路:如果树退化成一条链的话线段树就很明显了,然后这题就是套了个树连剖分,调了很久终于调出来第一个模板了 #inc ...

  9. SPOJ 375 Query on a tree(树链剖分)

    https://vjudge.net/problem/SPOJ-QTREE 题意: 给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值. 思路: 树链剖 ...

随机推荐

  1. NYOJ 305 表达式求值 (字符串处理)

    题目链接 描述 Dr.Kong设计的机器人卡多掌握了加减法运算以后,最近又学会了一些简单的函数求值,比如,它知道函数min(20,23)的值是20 ,add(10,98) 的值是108等等.经过训练, ...

  2. VC字体对话框的初始化

    本代码需要先添加类成员  LOGFONT lf; void CMyDlg::OnButton3() { // TODO: Add your control notification handler c ...

  3. Dijkstra算法(转)

    基本思想 通过Dijkstra计算图G中的最短路径时,需要指定起点s(即从顶点s开始计算). 此外,引进两个集合S和U.S的作用是记录已求出最短路径的顶点(以及相应的最短路径长度),而U则是记录还未求 ...

  4. php隐藏WEBSHELL技巧

    把shell添加到网站logo图片里: cat logo.png shell.php > logo.png 在网站任意一个php文件里添加下面的最简单方法: fputs(fopen('/home ...

  5. Ubuntu 上更新 Flash 插件

    2018-02-19 12:08:28 更新: 现在的 Google Chrome 浏览器自带了 Flash 支持,无需安装.而 Firefox 浏览器没有提供 Flash 支持,所以用 Firefo ...

  6. Ubuntu 14.04 开机手动开启numlock led

    在windows开机后,数字键盘灯是亮着的,但是当切换到ubuntu系统后登录用户名和密码时,如果你设定的有数字,都要先打开数字键盘区NUMLOCK键,然后再输入了,很不方便. 首先,需要安装一个小软 ...

  7. FileZilla 配置备份与还原【转】

    FileZilla是一款免费开源的FTP软件,安装和配置都很简单.在安装目录下的FileZilla Server Interface.xml和FileZilla Server.xml两个文件是程序的配 ...

  8. sicily 1017. Rate of Return

    Description Jill has been investing in a mutual fund for a while. Since her income has varied, the a ...

  9. centos上Jenkins搭建

    Jenkins可以提供持续集成服务,它的运行环境(runtime)需要Tomcat和JDK 要把Jenkins让Tomcat启动服务,而Tomcat需要JDK的环境 详情配置参见: http://ww ...

  10. SLD 官方实例

    基于xml标准的sld格式: <?xml version="1.0" encoding="UTF-8"?> <StyledLayerDescr ...