ztx

[WC2006]水管局长数据加强版

Posted on 2015年1月17日 17:43
/****************************************\
* Author : ztx
* Title  : [WC2006]水管局长数据加强版
* ALG    : LCT+Kruskal+离线
* CMT    : 通过构建最小生成树,然后转换成 寻找最近公共祖先来求解, 逆序处理询问,将删除改成添加边
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [WC2006]水管局长数据加强版
* ALG    : LCT+Kruskal+离线
* CMT    : 通过构建最小生成树,然后转换成 寻找最近公共祖先来求解, 逆序处理询问,将删除改成添加边
* Time   :
\****************************************/

#include <cstdio>
#include <algorithm>
	
int CH , NEG ;

inline int GETCHAR() {
	static const int LEN = 1<<15 ;
	static char BUF[LEN] , *S = BUF , *T = BUF ;
	if (S == T) {
		T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ;
		if (S == T) return EOF ;
	}
	return *S ++ ;
}

inline void read(int& ret) {
    ret = 0 ; while (CH=GETCHAR() , CH<'!') ;
    while (ret = (ret<<1)+(ret<<3)+CH-'0' , CH=GETCHAR() , CH>'!') ;
}

#define  maxn  100010LL
#define  maxm  1000010LL
#define  maxt  1100010LL
#define  maxe  2000010LL

int n , m , Q ;


struct EDGE { int u , v , w , id , del ; } e[maxm] ;
struct QUE { int cmd , u , v , id , ans ; } q[maxm] ;

bool CmpT(const EDGE& a , const EDGE& b) {
	if (a.u == b.u) return a.v < b.v ;
	else return a.u < b.u ;
}
bool CmpW(const EDGE& a , const EDGE& b) { return a.w < b.w ; }
bool CmpID(const EDGE& a , const EDGE& b) { return a.id < b.id ; }

int L , M , R ;
inline int Bsearch(int u , int v) {
	L = 1 , R = m ;
	while (R-L > 1) {
		/* (L , R] */
		M = L+(R-L)/2 ;
		if (e[M].u<u || (e[M].u==u&&e[M].v<v)) L = M ;
		else R = M ;
	}
	return R ;
}


int fa[maxt] = {0} , ch[maxt][2] = {0} ;
int maxv[maxt] = {0}/*Here are the labels stored*/ , val[maxt] = {0} ;
bool rev[maxt] = {0} ;

#define  null     0LL
#define  left(u)  ch[u][0]
#define  right(u) ch[u][1]

inline void Exchange(int& a , int& b) { int c = a ; a = b ; b = c ; }

inline bool isrt(int u) { return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; }

inline void Maintain(int u) {
	maxv[u] = u ;
	if (left(u) && val[maxv[left(u)]]>val[maxv[u]]) maxv[u] = maxv[left(u)] ;
	if (right(u) && val[maxv[right(u)]]>val[maxv[u]]) maxv[u] = maxv[right(u)] ;
}

inline void Clear(int u) {
	if (!u) return ;
	if (!isrt(u)) Clear(fa[u]) ;
	if (rev[u]) {
		rev[u] = false ;
		rev[left(u)] ^= true ;
		rev[right(u)] ^= true ;
		Exchange(left(u) , right(u)) ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) , Maintain(x) ;
}
 
inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (isrt(y)) {
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u]) Splay(u) , right(u) = v , v = u , Maintain(u) ;
}

inline void Makeroot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}

inline void Link(int u , int v) {
	Makeroot(u) , fa[u] = v ;
}

inline void Cut(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) , fa[u] = left(v) = null ;
}

inline int Query(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) ; return maxv[v] ;
}


int f[maxn] = {0} ;
inline int Father(int u) { return f[u] ? f[u] = Father(f[u]) : u ; }
inline bool Union(int u , int v) {
	u = Father(u) , v = Father(v) ;
	if (u == v) return false ;
	f[u] = v ; return true ;
}

int i , j , u , v , k , cnt = 0 ;
int main() {
	#define READ
	#ifdef  READ
		freopen("tube_strong.in" ,"r",stdin ) ;
		freopen("tube_strong.out","w",stdout) ;
	#endif

	read(n) , read(m) , read(Q) ;
	for (i = 1 ; i <= m ; i ++ ) {
		read(e[i].u) , read(e[i].v) , read(e[i].w) ;
		if (e[i].u > e[i].v) Exchange(e[i].u , e[i].v) ;
	}
	
	std::sort(e+1 , e+m+1 , CmpW) ;
	for (i = 1 ; i <= m ; i ++ ) {
		e[i].id = i ;
		val[i+n] = e[i].w , maxv[i+n] = i+n ;
		/* Edges are regarded as points */
	}
	/* Mark */
	std::sort(e+1 , e+m+1 , CmpT) ;
	for (i = 1 ; i <= Q ; i ++ ) {
		read(q[i].cmd) , read(q[i].u) , read(q[i].v) ;
		if (q[i].cmd == 2) {
			if (q[i].u > q[i].v) Exchange(q[i].u , q[i].v) ;
			j = Bsearch(q[i].u , q[i].v) ;
			e[j].del = true , q[i].id = e[j].id ;
		}
	}
	
	/* Kruskal */
	std::sort(e+1 , e+m+1 , CmpID) ;
	for (i = 1 ; i <= m ; i ++ ) {
		if (!e[i].del && Union(e[i].u , e[i].v)) {
			cnt ++ ;
			Link(e[i].u , i+n) ; Link(e[i].v , i+n) ;
			if (cnt == n-1) break ;
		}
	}
	
	for (i = Q ; i ; i -- ) {
		if (q[i].cmd == 1) q[i].ans = val[Query(q[i].u , q[i].v)] ;
		else {
			u = q[i].u , v = q[i].v , k = q[i].id ;
			j = Query(u , v) ;
			if (e[k].w < e[j-n].w) {
				Cut(e[j-n].u , j) , Cut(e[j-n].v , j) ;
				Link(u , k+n) , Link(v , k+n) ;
			}
		}
	}
	
	for (i = 1 ; i <= Q ; i ++ )
		if (q[i].cmd == 1) printf("%d\n", q[i].ans ) ;

	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}
/*
4 4 3
1 2 2
2 3 3
3 4 2
1 4 2
1 1 4
2 1 4
1 1 4
*/

tsinsen A1506. Missing On The Tree(张闻涛)

Posted on 2015年1月17日 17:42

 

/****************************************\
* Author : ztx
* Title  : tsinsen A1506. Missing On The Tree(张闻涛)
* ALG    : LCT
* CMT    : 推荐题解 http://ezreal-dn.com/archives/124
*  第一行一个数n 表示节点个数
*  第2到n行,每行一个数x,第i行的x表示i节点的父亲为x
*  接下来一个数m,表示操作与询问个数的总和
*  接下来m行,每行的开头有1个数p
*  若p为0,则接下来有2个数x,y,表示将x号节点的权值加上y
*  若p为1,则接下来有3个数x,y,z,表示将x号节点到y号节点的这条链上的每个节点的权值加上z
*  若p为2,则接下来有2个数x,y,表示将以x号节点为根的子树的每个节点的权值加上z
*  若p为3,则接下来有2个数x,y,表示询问x号节点到y号节点的这条链上每个节点的权值和,你需要输出这个和
*  若p为4,则接下来有2个数x,y,表示询问x号节点到y号节点的这条链上每个节点的权值的最大值,你需要输出这个最大值
*  若p为5,则接下来有2个数x,y,表示将x号节点的父亲改为y号节点
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : tsinsen A1506. Missing On The Tree(张闻涛)
* ALG    : LCT
* CMT    : 推荐题解 http://ezreal-dn.com/archives/124
*  第一行一个数n 表示节点个数
*  第2到n行,每行一个数x,第i行的x表示i节点的父亲为x
*  接下来一个数m,表示操作与询问个数的总和
*  接下来m行,每行的开头有1个数p
*  若p为0,则接下来有2个数x,y,表示将x号节点的权值加上y
*  若p为1,则接下来有3个数x,y,z,表示将x号节点到y号节点的这条链上的每个节点的权值加上z
*  若p为2,则接下来有2个数x,y,表示将以x号节点为根的子树的每个节点的权值加上z
*  若p为3,则接下来有2个数x,y,表示询问x号节点到y号节点的这条链上每个节点的权值和,你需要输出这个和
*  若p为4,则接下来有2个数x,y,表示询问x号节点到y号节点的这条链上每个节点的权值的最大值,你需要输出这个最大值
*  若p为5,则接下来有2个数x,y,表示将x号节点的父亲改为y号节点
* Time   :
\****************************************/

#include <cstdio>
#include <cstring>

int CH , NEG ;
inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = (ret<<1)+(ret<<3)+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}

#define  maxn     50010LL
#define  max(a,b) ((a)>(b)?(a):(b))
#define  infi     0x3f3f3f3fLL

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int val[maxn] = {0} , vir[maxn] = {0} ;/* u的值,与u相连的虚边的增值 */
int add[maxn] = {0} , chadd[maxn] = {0} ;/* val的标记,vir的标记 */
int size[maxn] = {0} , sum[maxn] = {0} , maxv[maxn] = {0} ;

#define null     0LL
#define left(u)  ch[u][0]
#define right(u) ch[u][1]

inline bool Isrt(int u) {
	return (!fa[u]) || ((left(fa[u])!=u)&&(right(fa[u])!=u)) ;
}

inline void Maintain(int u) {
	size[u] = 1 , sum[u] = maxv[u] = val[u] ;
	if (left(u)) {
		size[u] += size[left(u)] ;
		sum[u] += sum[left(u)] ;
		maxv[u] = max(maxv[left(u)] , maxv[u]) ;
	}
	if (right(u)) {
		size[u] += size[right(u)] ;
		sum[u] += sum[right(u)] ;
		maxv[u] = max(maxv[right(u)] , maxv[u]) ;
	}
}

inline void Add(int u , int w) {
	if (u) {
		val[u] += w ;
		sum[u] += size[u]*w ;
		maxv[u] += w ;
		add[u] += w ;
	}
}

inline void ChAdd(int u , int w) {
	if (u) {
		vir[u] += w ;
		chadd[u] += w ;
	}
}

inline void Clear(int u) {
	if (u) {
		if (add[u])
			Add(left(u) , add[u]) ,
			Add(right(u) , add[u]) ,
			add[u] = 0 ;
		if (chadd[u])
			ChAdd(left(u),chadd[u]) ,
			ChAdd(right(u),chadd[u]) ,
			chadd[u] = 0 ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			Clear(y) , Clear(x) ;
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			Clear(z) , Clear(y) , Clear(x) ;
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
	Maintain(x) ;
}

inline int Access(int u) {
	int v = null ;
	for ( ; u ; u = fa[u]) {
		Splay(u) ;
		if (v) Add(v,vir[u]) , ChAdd(v,vir[u]) ;
		if (right(u)) Add(right(u),-vir[u]) , ChAdd(right(u),-vir[u]) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
	return v ;
}

inline int LCA(int u , int v) {
	Access(u) ; return Access(v) ;
}

inline void Cut(int u) {
	Access(u) , Splay(u) ;
	fa[left(u)] = null ; left(u) = null ;
}

inline void Link(int u , int v) {
	Access(v) ;
	Splay(u) , fa[u] = v ;
	if (vir[v]) ChAdd(u,-vir[v]) ;
	if (vir[v]) Add(u,-vir[v]) ;
	Access(u) ;
}

void NodeAdd(int u , int w) {
	Access(u) , Splay(u) ; val[u] += w ;
}

void ChainAdd(int u , int v , int w) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (v) Add(v,vir[u]) , ChAdd(v,vir[u]) ;
		/*虚边变实边*/
		if (!fa[u]) Add(v,w) , Add(right(u),w) , val[u] += w ;
		/*打标记*/
		if (right(u)) Add(right(u),-vir[u]) , ChAdd(right(u),-vir[u]) ;
		/*实边变虚边*/
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void SubtreeAdd(int u , int w) {
	Access(u) , Splay(u) ;
	val[u] += w , vir[u] += w ;
}

void ChainSum(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (v) Add(v,vir[u]) , ChAdd(v,vir[u]) ;
		if (!fa[u]) printf("%d\n",val[u]+sum[v]+sum[right(u)]) ;
		if (right(u)) Add(right(u),-vir[u]) , ChAdd(right(u),-vir[u]) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void ChainMax(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (v) Add(v,vir[u]) , ChAdd(v,vir[u]) ;
		if (!fa[u]) printf("%d\n",max(max(val[u],maxv[v]),maxv[right(u)])) ;
		if (right(u)) Add(right(u),-vir[u]) , ChAdd(right(u),-vir[u]) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void ChangeFather(int u , int v) {
	if (LCA(u,v)==u) return ;
	Cut(u) , Link(u,v) ;
}

int n , cmd , u , v , w , Q ;

int main() {
//    #define READ
    #ifdef  READ
        freopen(".in" ,"r",stdin ) ;
        freopen(".out","w",stdout) ;
    #endif
    read(n) ;
    for (u = 2 ; u <= n ; u ++ ) {
    	read(v) ; fa[u] = v ;
	}
	for (u = 1 ; u <= n ; u ++ ) size[u] = 1 ;
	val[null] = maxv[null] = -infi ; sum[null] = 0 ;
	read(Q) ;
	while ( Q -- ) {
		read(cmd) , read(u) , read(v) ;
		if (cmd == 0) NodeAdd(u , v) ;
		else if (cmd == 1) read(w) , ChainAdd(u , v , w) ;
		else if (cmd == 2) SubtreeAdd(u , v) ;
		else if (cmd == 3) ChainSum(u , v) ;
		else if (cmd == 4) ChainMax(u , v) ;
		else if (cmd == 5) ChangeFather(u , v) ;
	}
    #ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}
/*
3
1
1
2
1 2 3 -1
3 2 3
*/

[国家集训队2011]旅游(宋方睿)

Posted on 2015年1月17日 17:40
/****************************************\
* Author : ztx
* Title  : [国家集训队2011]旅游(宋方睿)
* ALG    : LCT
* CMT    : 将边权存到点上, 于是成了一棵有根树那么不换根地进行操作即可
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [国家集训队2011]旅游(宋方睿)
* ALG    : LCT
* CMT    : 将边权存到点上, 于是成了一棵有根树那么不换根地进行操作即可
* Time   :
\****************************************/

#include <cstdio>
#include <cstring>

int CH , NEG ;
inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}

inline void reads(int& ret) {
	while (ret=getchar() , ret<'!') ;
	if (ret == 'M') ret += getchar() ;
	while (CH=getchar() , CH>'!') ;
}

#define  maxn     100010LL
#define  maxe     200010LL
#define  infi     0x7f7f7f7fLL
#define  max(a,b) ((a)>(b)?(a):(b))
#define  min(a,b) ((a)<(b)?(a):(b))

struct FST { int to , next , val ; } e[maxe] ;
int star[maxn] = {0} , tote = 1 ;/* ! */
void AddEdge(int u , int v , int w) {
	e[++tote].to = v ; e[tote].val = w ; e[tote].next = star[u] ; star[u] = tote ;
	e[++tote].to = u ; e[tote].val = w ; e[tote].next = star[v] ; star[v] = tote ;
}

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int val[maxn] = {0} , sum[maxn] = {0} ;
int maxv[maxn] = {0} , minv[maxn] = {0} ;
bool neg[maxn] = {0} ;

int belong[maxn] = {0} ;

#define null     0LL
#define left(u)  ch[u][0]
#define right(u) ch[u][1]

inline void Exchange(int&u,int&v) {int w=u;u=v;v=w;}
inline bool Isrt(int u) {
	return (!fa[u]) || ((left(fa[u])!=u)&&(right(fa[u])!=u)) ;
}

inline void Maintain(int u) {
	sum[u] = maxv[u] = minv[u] = val[u] ;
	if (left(u)) {
		sum[u] += sum[left(u)] ;
		maxv[u] = max(maxv[left(u)] , maxv[u]) ;
		minv[u] = min(minv[left(u)] , minv[u]) ;
	}
	if (right(u)) {
		sum[u] += sum[right(u)] ;
		maxv[u] = max(maxv[right(u)] , maxv[u]) ;
		minv[u] = min(minv[right(u)] , minv[u]) ;
	}
}

inline void Change(int u) {
	if (u) {
		neg[u] ^= true ;
		val[u] = -val[u] ;
		sum[u] = -sum[u] ;
		maxv[u] = -maxv[u] ;
		minv[u] = -minv[u] ;
		Exchange(maxv[u] , minv[u]) ;
	}
}

inline void Clear(int u) {
	if (u && neg[u]) {
		Change(left(u)) ;
		Change(right(u)) ;
		neg[u] = false ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			Clear(y) , Clear(x) ;
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			Clear(z) , Clear(y) , Clear(x) ;
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
	Maintain(x) ;
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u]) {
		Splay(u) ; Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

int vis[maxn] = {0} ;
void BuildTree(int u) {
	vis[u] = true ;
	int p , v ;
	for (p=star[u] ; p ; p =e[p].next) {
		v = e[p].to ;
		if (!vis[v]) {
			fa[v] = u ;
			sum[v] = val[v] = e[p].val ;
			belong[p>>1] = v ;
			BuildTree(v) ;
		}
	}
}

void CHANGE(int u , int w) {
	u = belong[u] ; Splay(u) ; val[u] = w ;
}

void NEGATE(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			Change(v) , Change(right(u)) ;
			Maintain(u) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void SUM(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			printf("%d\n", sum[v]+sum[right(u)] ) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void MAX(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			printf("%d\n", max(maxv[v] , maxv[right(u)])) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void MIN(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			printf("%d\n", min(minv[v] , minv[right(u)])) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

int n , i , u , v , w , Q ;

int main() {
    #define READ
    #ifdef  READ
        freopen("nt2011_travel.in" ,"r",stdin ) ;
        freopen("nt2011_travel.out","w",stdout) ;
    #endif
    read(n) ;
    for (i = 1 ; i < n ; i ++ ) {
    	read(u) , read(v) , read(w) ;
    	AddEdge(++u , ++v , w) ;
	}
	sum[null] = 0 ;
	maxv[null] = -infi ;
	minv[null] = infi ;
	BuildTree(1) ;
	read(Q) ;
	while ( Q -- ) {
		reads(i) , read(u) , read(v) ;
		u ++ , v ++ ;
		if (i == 'C') CHANGE(--u , --v) ;
		else if (i == 'N') NEGATE(u , v) ;
		else if (i == 'S') SUM(u , v) ;
		else if (i == 'M'+'A') MAX(u , v) ;
		else if (i == 'M'+'I') MIN(u , v) ;
	}
    #ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}

[NOI2014]魔法森林

Posted on 2015年1月17日 17:35
/****************************************\
* Author : ztx
* Title  : [NOI2014]魔法森林
* ALG    : LCT+Kruskal
* CMT    :
* 把边按a从小到大排序
* 然后一条条加边
* 动态维护b的最小生成树
* 假设现在加入的边是(x,y) a b
* 那么答案=min(答案,a+树上1到n路径上的b的最大值)
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [NOI2014]魔法森林
* ALG    : LCT+Kruskal
* CMT    :
* 把边按a从小到大排序
* 然后一条条加边
* 动态维护b的最小生成树
* 假设现在加入的边是(x,y) a b
* 那么答案=min(答案,a+树上1到n路径上的b的最大值)
* Time   :
\****************************************/

#include <cstdio>
#include <algorithm>

int CH , NEG ;

inline int GETCHAR() {
	static const int LEN = 1<<15 ;
	static char BUF[LEN] , *S = BUF , *T = BUF ;
	if (S == T) {
		T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ;
		if (S == T) return EOF ;
	}
	return *S ++ ;
}

inline void read(int& ret) {
    ret = 0 ; while (CH=GETCHAR() , CH<'!') ;
    while (ret = (ret<<1)+(ret<<3)+CH-'0' , CH=GETCHAR() , CH>'!') ;
}

#define  maxn  50010LL
#define  maxm  100010LL
#define  maxt  150010LL
#define  infi  0x7f7f7f7fLL

int n , m , Q , ans = infi , ansa ;

struct EDGE { int u , v , a , b ; } e[maxm] ;

bool Cmpa(const EDGE& a , const EDGE& b) {
	if (a.a == b.a) return a.b < b.b ;
	else return a.a < b.a ;
}


int fa[maxt] = {0} , ch[maxt][2] = {0} ;
int maxb[maxt] = {0}/*Here are the labels stored*/ , val[maxt] = {0} ;
bool rev[maxt] = {0} ;

#define  null     0LL
#define  left(u)  ch[u][0]
#define  right(u) ch[u][1]

inline void Exchange(int& a , int& b) { int c = a ; a = b ; b = c ; }

inline bool Isrt(int u) { return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; }

inline void Maintain(int u) {
	maxb[u] = u ;
	if (left(u) && val[maxb[left(u)]]>val[maxb[u]]) maxb[u] = maxb[left(u)] ;
	if (right(u) && val[maxb[right(u)]]>val[maxb[u]]) maxb[u] = maxb[right(u)] ;
}

inline void Clear(int u) {
	if (!u) return ;
	if (!Isrt(u)) Clear(fa[u]) ;
	if (rev[u]) {
		rev[u] = false ;
		rev[left(u)] ^= true ;
		rev[right(u)] ^= true ;
		Exchange(left(u) , right(u)) ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u]) Splay(u) , right(u) = v , v = u , Maintain(u) ;
}

inline void Makeroot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}

inline void Link(int u , int v) {
	Makeroot(u) , fa[u] = v ;
}

inline void Cut(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) , fa[u] = left(v) = null ;
}

inline int Query(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) ; return maxb[v] ;
}


int f[maxn] = {0} ;
inline int GetAnc(int u) { return f[u] ? f[u] = GetAnc(f[u]) : u ; }
inline bool Union(int u , int v) {
	u = GetAnc(u) , v = GetAnc(v) ;
	if (u == v) return false ;
	f[u] = v ; return true ;
}

int i , j , cnt = 0 ;
int main() {
	#define READ
	#ifdef  READ
		freopen("magicalforest.in" ,"r",stdin ) ;
		freopen("magicalforest.out","w",stdout) ;
	#endif

	read(n) , read(m) ;
	for (i = 1 ; i <= m ; i ++ ) {
		read(e[i].u) , read(e[i].v) , read(e[i].a) , read(e[i].b) ;
	}

	std::sort(e+1 , e+m+1 , Cmpa) ;
	for (i = 1 ; i <= m ; i ++ ) {
		val[i+n] = e[i].b , maxb[i+n] = i+n ;
		/* Edges are regarded as points */
	}

	/* Kruskal */
	cnt = 0 ;
	for (i = 1 ; i <= m ; i ++ ) {
		if (Union(e[i].u , e[i].v)) {
			Link(e[i].u , i+n) , Link(e[i].v , i+n) ;
		} else {
			j = Query(e[i].u , e[i].v) ;
			if (e[i].b < val[j]) {
				Cut(e[j-n].u , j) , Cut(e[j-n].v , j) ;
				Link(e[i].u , i+n) , Link(e[i].v , i+n) ;

			}
		}
		if (GetAnc(1) == GetAnc(n)) {
			ansa = val[Query(1 , n)]+e[i].a ;
			if (ansa < ans) ans = ansa ;
		}
	}
	if (ans == infi) ans = -1 ;
	printf("%d\n", ans ) ;

	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}
/*
4 5
1 2 19 1
2 3 8 12
2 4 12 15
1 3 17 8
3 4 1 17

3 1
1 2 1 1

*/

[AHOI2005]LANE 航线规划

Posted on 2015年1月17日 17:31
/****************************************\
* Author : ztx
* Title  : [AHOI2005]LANE 航线规划
* ALG    : Tarjan+LCT+离线+瞎搞
* CMT    : "无论航线如何被破坏,任意时刻任意两个星球都能够相互到达":
*             连通图,缩点后不是森林
*          "在整个数据中,任意两个星球之间最多只可能存在一条直接的航线":
*             无重边
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [AHOI2005]LANE 航线规划
* ALG    : Tarjan+LCT+离线+瞎搞
* CMT    : "无论航线如何被破坏,任意时刻任意两个星球都能够相互到达":
*             连通图,缩点后不是森林
*          "在整个数据中,任意两个星球之间最多只可能存在一条直接的航线":
*             无重边
* Time   :
\****************************************/

#include <cstdio>

int CH , NEG ;

inline int GETCHAR() {
	static const int LEN = 1<<15 ;
	static char BUF[LEN] , *S = BUF , *T = BUF ;
	if (S == T) {
		T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ;
		if (S == T) return EOF ;
	}
	return *S ++ ;
}

inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=GETCHAR() , CH<'!') ;
    if (CH == '-') NEG = true , CH = GETCHAR() ;
    while (ret=(ret<<1)+(ret<<3)+CH-'0' , CH=GETCHAR() , CH>'!') ;
    if (NEG) ret = -ret ;
}

#include <algorithm>
#include <cstring>

#define  maxn  30010LL
#define  maxm  1000010LL
#define  maxe  2000010LL
#define  maxq  40010LL
#define  infi  0x3f3f3f3fLL

int n , m , Q ;

struct FST { int to , next ; } e1[maxe] , e2[maxe] ;
int star1[maxn] = {0} , star2[maxn] = {0} , tote1 = 0 , tote2 = 0 ;

void AddEdge(int u , int v) {
	e1[++tote1].to = v ; e1[tote1].next = star1[u] ; star1[u] = tote1 ;
	e1[++tote1].to = u ; e1[tote1].next = star1[v] ; star1[v] = tote1 ;
}

void BCCAddEdge(int u , int v) {
	e2[++tote2].to = v ; e2[tote2].next = star2[u] ; star2[u] = tote2 ;
	e2[++tote2].to = u ; e2[tote2].next = star2[v] ; star2[v] = tote2 ;
}


struct QUE { int cmd , u , v , id , ans ; } q[maxq] ;


struct EDGE { int u , v , del ; EDGE() { del = false ; } } e[maxm] ;
int tote = 0 ;

bool CmpT(const EDGE& a , const EDGE&b) {
	if (a.u == b.u) return a.v < b.v ;
	return a.u < b.u ;
}

int L , M , R ;
inline int Bsearch(int u , int v) {
	L = 1 , R = m ;
	while (R-L > 1) {
		/* (L , R] */
		M = L+(R-L)/2 ;
		if (e[M].u<u || (e[M].u==u&&e[M].v<v)) L = M ;
		else R = M ;
	}
	return R ;
}


int f[maxn] = {0} ;
inline int GetAnc(int u) { return f[u] ? f[u] = GetAnc(f[u]) : u ; }
inline void Union(int u , int v) {
	u = GetAnc(u) , v = GetAnc(v) ;
	if (u != v) f[u] = v ;
}


int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int size[maxn] = {0} ;
bool rev[maxn] = {0} ;

#define  null     0LL
#define  left(u)  ch[u][0]
#define  right(u) ch[u][1]

template<typename T>inline void Exchange(T&a , T&b) { T c=a;a=b;b=c; }

inline bool Isrt(int u) { fa[u] = GetAnc(fa[u]) ; return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; }

inline void Maintain(int u) {
	size[u] = 1 ;
	if (left(u)) size[u] += size[left(u)] ;
	if (right(u)) size[u] += size[right(u)] ;
}

inline void Clear(int u) {
	if (!u) return ;
	if (!Isrt(u)) Clear(fa[u]) ;
	if (rev[u]) {
		rev[u] = false ;
		rev[left(u)] ^= true ;
		rev[right(u)] ^= true ;
		Exchange(left(u) , right(u)) ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
    	y = fa[x] = GetAnc(fa[x]) , z = fa[y] = GetAnc(fa[y]) ;
		if (Isrt(y)) {
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u] = GetAnc(fa[u])) Splay(u) , right(u) = v , v = u , Maintain(u) ;
}

inline void Makeroot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}


int DFN[maxn] = {0} , LOW[maxn] = {0} , Belong[maxn] = {0} ;
int Stap[maxn] = {0} ;
int Stop , Bcnt , Dindex ;

void DFS(int from , int u) {
	int v = 0 ;
    DFN[u] = LOW[u] = ++Dindex , Stap[++Stop] = u ;
    for (int p = star1[u] ; p ; p = e1[p].next) {
    	v = e1[p].to ;
    	if (from == v) continue ;
    	if (!DFN[v]) {
			DFS(u , v) ; if (LOW[u] > LOW[v]) LOW[u] = LOW[v] ;
			if (DFN[u] < LOW[v]) {
				Bcnt ++ ;
				for ( ; Stap[Stop]!=v ; ) {
					Belong[Stap[Stop--]] = Bcnt ;
				}
				if (Stap[Stop]==v) Belong[Stap[Stop--]] = Bcnt ;
        	}
		} else if (LOW[u] > DFN[v]) LOW[u] = DFN[v] ;
    }
}

void Tarjan() {
    Stop = Bcnt = Dindex = 0 ;
    memset(DFN , 0 , sizeof(DFN)) ;
    DFS(0 , 1) ;
    Bcnt ++ ; while (Stop) Belong[Stap[Stop--]] = Bcnt ;
}


bool vis[maxn] = {0} ;
void BuildTree(int u) {
	if (vis[u]) return ; vis[u] = size[u] = 1 ;
	int p , v ;
	for (p = star2[u] ; p ; p = e2[p].next) {
		v = e2[p].to ;
		if (!vis[v]) {
			fa[v] = u ; BuildTree(v) ;
		}
	}
}

void Shrink(int from , int u) {
	if (!u) return ;
	if (from) Union(from , u) ;
	if (left(u)) Shrink(u , left(u)) ;
	if (right(u)) Shrink(u , right(u)) ;
}

int i , j , u , v , k , cnt = 0 ;
int main() {
	#define READ
	#ifdef  READ
		freopen("lane.in" ,"r",stdin ) ;
		freopen("lane.out","w",stdout) ;
	#endif
	/* 读入 */
	read(n) , read(m) ;
	for (i = 1 ; i <= m ; i ++ ) {
		read(e[i].u) , read(e[i].v) ;
		if (e[i].u > e[i].v) Exchange(e[i].u , e[i].v) ;
	}

	/* 标记删除边 */
	std::sort(e+1 , e+m+1 , CmpT) ;
	for (Q = 0 ; true ; ) {
		read(q[Q+1].cmd) ;
		if (q[Q+1].cmd == -1) break ;
		Q ++ ; read(q[Q].u) , read(q[Q].v) ;
		if (q[Q].cmd == 0) {
			if (q[Q].u > q[Q].v) Exchange(q[Q].u , q[Q].v) ;
			e[Bsearch(q[Q].u , q[Q].v)].del = true ;
		}
	}

	/* 对最终状态建图 */
	for (i = 1 ; i <= m ; i ++ ) {
		if (e[i].del) continue ;
		AddEdge(e[i].u , e[i].v) ;
	}

	/* Tarjan求双联通分量 */
	Tarjan() ;

	/* 对缩点后的联通块建图 */
	for (i = 1 ; i <= m ; i ++ ) {
		if (e[i].del) continue ;
		u = Belong[e[i].u] , v = Belong[e[i].v] ;
		if (u != v) BCCAddEdge(u , v) ;
	}

	/* 对联通块建树 */
	BuildTree(1) ;

	/* 回答询问 */
	for (i = Q ; i ; i -- ) {
		u = GetAnc(Belong[q[i].u]) , v = GetAnc(Belong[q[i].v]) ;
		if (q[i].cmd == 1) {
			if (u == v) q[i].ans = 0 ;
			else {
				Makeroot(u) ; Access(v) , Splay(v) ; q[i].ans = size[v]-1 ;
			}
		} else if (u != v) {
			Makeroot(u) ; Access(v) , Splay(v) ; Shrink(null , v) ; fa[GetAnc(v)] = null ;
		}
	}

	for (i = 1 ; i <= Q ; i ++ )
		if (q[i].cmd == 1) printf("%d\n", q[i].ans ) ;

	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}
/*
9 10
1 2
2 3
2 4
2 6
3 5
3 6
4 6
4 8
6 7
7 9
1 1 7
-1


20 35
1 2
1 3
1 4
1 8
1 11
1 16
2 3
2 5
2 7
2 11
2 19
3 8
3 9
3 10
4 6
4 9
4 11
4 15
4 19
5 8
5 11
5 16
5 17
6 12
6 14
6 16
7 10
7 11
7 13
7 19
8 9
9 18
10 14
14 20
17 18

0 8 9
0 1 8
1 7 20
1 5 15
1 12 14
0 6 16
1 14 8
1 17 2
0 6 14
1 5 6
0 17 18
1 14 9

-1

*/

[国家集训队2012]tree(伍一鸣)

Posted on 2015年1月17日 17:28
/****************************************\
* Author : ztx
* Title  : [国家集训队2012]tree(伍一鸣)
* ALG    : LCT
* CMT    :
* 这个么.....使劲打标记吧
* 先乘法后加法, 和线段树维护是差不多的
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [国家集训队2012]tree(伍一鸣)
* ALG    : LCT
* CMT    :
* 这个么.....使劲打标记吧
* 先乘法后加法, 和线段树维护是差不多的
* Time   :
\****************************************/

#include <cstdio>

int CH , NEG ;
inline int GETCHAR() {
	static const int LEN = 21000000 ;
	static char BUF[LEN] , *S = BUF , *T = BUF ;
	if (S == T) {
		T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ;
		if (S == T) return EOF ;
	}
	return *S ++ ;
}

inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=GETCHAR() , CH<'!') ;
    if (CH == '-') NEG = true , CH = GETCHAR() ;
    while (ret = ret*10+CH-'0' , CH=GETCHAR() , CH>'!') ;
    if (NEG) ret = -ret ;
}

inline void reads(int& ret) {
	while (ret=GETCHAR() , ret<'!') ;
	while (CH=GETCHAR() , CH>'!') ;
}

#define  maxn    100010LL
#define  maxe    200010LL
#define  ansmod  51061

typedef unsigned int uint ;

struct FST { int to , next ; } e[maxe] ;
int star[maxn] = {0} , tote = 0 ;
void AddEdge(int u , int v) {
	e[++tote].to = v ; e[tote].next = star[u] , star[u] = tote ;
}

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
bool rev[maxn] = {0} ;
uint size[maxn] = {0} , val[maxn] = {0} ;
uint mul[maxn] = {0} , add[maxn] = {0} , sum[maxn] = {0} ;

#define  null     0LL
#define  left(u)  ch[u][0]
#define  right(u) ch[u][1]

inline void Exchange(int& a , int& b) { int c = a ; a = b ; b = c ; }

inline bool Isrt(int u) { return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; }

inline void Maintain(int u) {
	if (!u) return ;
	sum[u] = val[u]%ansmod , size[u] = 1 ;
	if (left(u)) {
		sum[u] += sum[left(u)] , sum[u] %= ansmod ;
		size[u] += size[left(u)] ;
	}
	if (right(u)) {
		sum[u] += sum[right(u)] , sum[u] %= ansmod ;
		size[u] += size[right(u)] ;
	}
}

void Mul(int u , uint w) {
	if (!u) return ;
	val[u] *= w , val[u] %= ansmod ;
	sum[u] *= w , sum[u] %= ansmod ;
	mul[u] *= w , mul[u] %= ansmod ;
	add[u] *= w , add[u] %= ansmod ;
}

void Add(int u , uint w) {
	if (!u) return ;
	val[u] += w , val[u] %= ansmod ;
	sum[u] += w*size[u] , sum[u] %= ansmod ;
	add[u] += w , add[u] %= ansmod ;
}

inline void Clear(int u) {
	if (!u) return ;
	if (mul[u] != 1) {
		Mul(left(u) , mul[u]) ;
		Mul(right(u) , mul[u]) ;
		mul[u] = 1 ;
	}
	if (add[u]) {
		Add(left(u) , add[u]) ;
		Add(right(u) , add[u]) ;
		add[u] = 0 ;
	}
	if (rev[u]) {
		rev[u] = false ;
		rev[left(u)] ^= true ;
		rev[right(u)] ^= true ;
		Exchange(left(u) , right(u)) ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) , Maintain(x) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		Clear(z) , Clear(y) , Clear(x) ;
		if (Isrt(y)) {
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
}

inline int Access(int u) {
	int v = null ;
	for ( ; u ; u = fa[u]) Splay(u) , right(u) = v , v = u , Maintain(u) ;
	return v ;
}

inline void Makeroot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}

inline void Link(int u , int v) {
	Makeroot(u) , fa[u] = v ;
}

inline void Cut(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) , fa[u] = left(v) = null ; Maintain(v) ;
}

bool vis[maxn] = {0} ;
void BuildTree(int u) {
	if (vis[u]) return ; vis[u] = true ;
	size[u] = val[u] = sum[u] = mul[u] = 1 ;
	int p , v ;
	for (p = star[u] ; p ; p = e[p].next) {
		v = e[p].to ;
		if (!vis[v]) {
			fa[v] = u ; BuildTree(v) ;
		}
	}
}

int n , Q , cmd , u , v , w , i ;

int main() {
	#define READ
	#ifdef  READ
		freopen("nt2012_wym_tree.in" ,"r",stdin ) ;
		freopen("nt2012_wym_tree.out","w",stdout) ;
	#endif

	read(n) , read(Q) ;
	for (i = 1 ; i < n ; i ++ ) {
		read(u) , read(v) ;
		AddEdge(u , v) , AddEdge(v , u) ;
	}
	BuildTree(1) ;
	while ( Q -- ) {
		reads(cmd) , read(u) , read(v) ;
		if (cmd == '+') {
			read(w) ;
			Makeroot(u) , Access(v) , Splay(v) ;
			Add(v , w) ;
		} else if (cmd == '-') {
			Cut(u , v) ; read(u) , read(v) ;
			Link(u , v) ;
		} else if (cmd == '*') {
			read(w) ;
			Makeroot(u) , Access(v) , Splay(v) ;
			Mul(v , w) ;
		} else if (cmd == '/') {
			Makeroot(u) , Access(v) , Splay(v) ;
			printf("%d\n", sum[v] ) ;
		}
	}
	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}

[SDOI2008]Cave 洞穴勘测

Posted on 2015年1月17日 17:26
/****************************************\
* Author : ztx
* Title  : [SDOI2008]Cave 洞穴勘测
* ALG    : LCT
* CMT    : 判断连通性
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [SDOI2008]Cave 洞穴勘测
* ALG    : LCT
* CMT    : 判断连通性
* Time   :
\****************************************/

#include <cstdio>

int CH , NEG ;
inline int GETCHAR() {
	static const int LEN = 1<<15 ;
	static char BUF[LEN] , *S = BUF , *T = BUF ;
	if (S == T) {
		T = (S=BUF)+fread(BUF , 1 , LEN , stdin) ;
		if (S == T) return EOF ;
	}
	return *S ++ ;
}

inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=GETCHAR() , CH<'!') ;
    if (CH == '-') NEG = true , CH = GETCHAR() ;
    while (ret = ret*10+CH-'0' , CH=GETCHAR() , CH>'!') ;
    if (NEG) ret = -ret ;
}

inline void reads(int& ret) {
	while (ret=GETCHAR() , ret<'!') ;
	while (CH=GETCHAR() , CH>'!') ;
}

#define  maxn  10010LL

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
bool rev[maxn] = {0} ;

#define  null     0LL
#define  left(u)  ch[u][0]
#define  right(u) ch[u][1]

inline void Exchange(int& a , int& b) { int c = a ; a = b ; b = c ; }

inline bool Isrt(int u) { return (fa[u]==null)||(left(fa[u])!=u&&right(fa[u])!=u) ; }

inline void Clear(int u) {
	if (!u) return ;
	if (!Isrt(u)) Clear(fa[u]) ;
	if (rev[u]) {
		rev[u] = false ;
		rev[left(u)] ^= true ;
		rev[right(u)] ^= true ;
		Exchange(left(u) , right(u)) ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
}

inline int Access(int u) {
	int v = null ; for ( ; u ; u = fa[u]) Splay(u) , right(u) = v , v = u ; return v ;
}

inline void Makeroot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}

inline void Link(int u , int v) {
	Makeroot(u) , fa[u] = v ;
}

inline void Cut(int u , int v) {
	Makeroot(u) ; Access(v) , Splay(v) , fa[u] = left(v) = null ;
}

inline int Getroot(int u) {
	for (u = Access(u) ; Clear(u) , left(u) ; u = left(u)) ; return u ;
}

inline void Query(int u , int v) {
	u = Getroot(u) , v = Getroot(v) ;
	printf("%s\n", u==v ? "Yes" : "No") ;
}

int n , m , cmd , u , v ;

int main() {
	#define READ
	#ifdef  READ
		freopen("sdoi2008_cave.in" ,"r",stdin ) ;
		freopen("sdoi2008_cave.out","w",stdout) ;
	#endif
	read(n) , read(m) ;
	while ( m -- ) {
		reads(cmd) , read(u) , read(v) ;
		if (cmd == 'C') Link(u , v) ;
		if (cmd == 'D') Cut(u , v) ;
		if (cmd == 'Q') Query(u , v) ;
	}
	#ifdef  READ
		fclose(stdin) ; fclose(stdout) ;
	#else
		getchar() ; getchar() ;
	#endif
	return 0 ;
}

[POJ3237]树的维护

Posted on 2015年1月17日 17:25
/****************************************\
* Author : ztx
* Title  : [POJ3237]树的维护
* ALG    : LCT
* CMT    :
* 很明显的动态树模型, 首先要把边权转化为点权,
* 并且要在dfs的时候记录每条边的权值在哪个点里面.
* 操作1 和3 是常规操作.
* 对于操作2, 我们对每个节点记录Max和Min, 取反就等价于Max = -Min , Min = -Max
* Time   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [POJ3237]树的维护
* ALG    : LCT
* CMT    :
* 很明显的动态树模型, 首先要把边权转化为点权,
* 并且要在dfs的时候记录每条边的权值在哪个点里面.
* 操作1 和3 是常规操作.
* 对于操作2, 我们对每个节点记录Max和Min, 取反就等价于Max = -Min , Min = -Max
* Time   :
\****************************************/

#include <cstdio>
#include <cstring>

int CH , NEG ;
inline void read(int& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}

inline void reads(int& ret) {
	while (ret=getchar() , ret<'!') ;
	while (CH=getchar() , CH>'!') ;
}

#define  maxn     10010LL
#define  maxe     20010LL
#define  infi     0x7f7f7f7fLL
#define  max(a,b) ((a)>(b)?(a):(b))
#define  min(a,b) ((a)<(b)?(a):(b))

struct FST { int to , next , val ; } e[maxe] ;
int star[maxn] = {0} , tote = 1 ;/* ! */
void AddEdge(int u , int v , int w) {
	e[++tote].to = v ; e[tote].val = w ; e[tote].next = star[u] ; star[u] = tote ;
	e[++tote].to = u ; e[tote].val = w ; e[tote].next = star[v] ; star[v] = tote ;
}

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int val[maxn] = {0} , maxv[maxn] = {0} , minv[maxn] = {0} ;
bool neg[maxn] = {0} ;

int belong[maxn] = {0} ;

#define null     0LL
#define left(u)  ch[u][0]
#define right(u) ch[u][1]

inline void Exchange(int&u,int&v) {int w=u;u=v;v=w;}
inline bool Isrt(int u) {
	return (!fa[u]) || ((left(fa[u])!=u)&&(right(fa[u])!=u)) ;
}

inline void Maintain(int u) {
	maxv[u] = minv[u] = val[u] ;
	if (left(u)) {
		maxv[u] = max(maxv[left(u)] , maxv[u]) ;
		minv[u] = min(minv[left(u)] , minv[u]) ;
	}
	if (right(u)) {
		maxv[u] = max(maxv[right(u)] , maxv[u]) ;
		minv[u] = min(minv[right(u)] , minv[u]) ;
	}
}

inline void Negated(int u) {
	if (u) {
		neg[u] ^= true ;
		val[u] = -val[u] ;
		maxv[u] = -maxv[u] ;
		minv[u] = -minv[u] ;
		Exchange(maxv[u] , minv[u]) ;
	}
}

inline void Clear(int u) {
	if (u && neg[u]) {
		Negated(left(u)) ;
		Negated(right(u)) ;
		neg[u] = false ;
	}
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			Clear(y) , Clear(x) ;
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			Clear(z) , Clear(y) , Clear(x) ;
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
	Maintain(x) ;
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u]) {
		Splay(u) ; Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

int vis[maxn] = {0} ;
void Build(int u) {
	vis[u] = true ;
	int p , v ;
	for (p=star[u] ; p ; p =e[p].next) {
		v = e[p].to ;
		if (vis[v]) fa[u] = v ;
		else {
			val[v] = e[p].val ;
			belong[p>>1] = v ;
			Build(v) ;
		}
	}
}

void CHANGE(int u , int w) {
	u = belong[u] ; Splay(u) ; val[u] = w ;
}

void NEGATE(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			Negated(v) , Negated(right(u)) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

void QUERY(int u , int v) {
	Access(v) ;
	for (v = null ; u ; u = fa[u]) {
		Splay(u) ;
		if (!fa[u]) {
			printf("%d\n", max(maxv[v] , maxv[right(u)])) ;
			return ;
		}
		Clear(u) ;
		right(u) = v , v = u ; Maintain(u) ;
	}
}

int n , i , u , v , w ;

int main() {
    #define READ
    #ifdef  READ
        freopen("maintaintree.in" ,"r",stdin ) ;
        freopen("maintaintree.out","w",stdout) ;
    #endif
    read(n) ;
    for (i = 1 ; i < n ; i ++ ) {
    	read(u) , read(v) , read(w) ;
    	AddEdge(u , v , w) ;
	}
	maxv[null] = -infi , minv[null] = infi ;
	Build(1) ;
	while (reads(i) , i!='D') {
		read(u) , read(v) ;
		if (i == 'C') CHANGE(u , v) ;
		if (i == 'Q') QUERY(u , v) ;
		if (i == 'N') NEGATE(u , v) ;
	}
    #ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}

[SDOI2011]染色

Posted on 2015年1月17日 17:21
/****************************************\
* Author : ztx
* Title  : [SDOI2011]染色
* ALG    : LCT
* CMT    :
* 多打打标记就好了嘛~
* Data   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [SDOI2011]染色
* ALG    : LCT
* CMT    :
* 多打打标记就好了嘛~
* Data   :
\****************************************/

#include <cstdio>

int CH ;
inline void read(int& ret) {
    ret = 0 ; while (CH=getchar() , CH<'!') ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
}

#define  maxn  100010LL
#define  maxe  200010LL

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int cover[maxn] = {0} ;
int color[maxn] = {0} , lcolor[maxn] = {0} , rcolor[maxn] = {0} , d[maxn] = {0} ;

#define  null      0LL
#define  left(u)   ch[u][0]
#define  right(u)  ch[u][1]

inline bool Isrt(int u){ return ((!fa[u])||(fa[u]&&(left(fa[u])!=u)&&(right(fa[u])!=u))) ; }
inline void Maintain(int u) {
    lcolor[u] = left(u) ? lcolor[left(u)] : color[u] ;
    rcolor[u] = right(u) ? rcolor[right(u)] : color[u] ;
    d[u] = d[left(u)]+1+d[right(u)]-(rcolor[left(u)]==color[u])-(lcolor[right(u)]==color[u]) ;
}

inline void Paint(int u , int col) {
    if (!u) return ;
    lcolor[u] = rcolor[u] = color[u] = cover[u] = col ; d[u] = 1 ;
}

inline void Clear(int u) {
	if (!u) return ;
    if (!Isrt(u)) Clear(fa[u]) ;
    if (cover[u]) {
        Paint(left(u) , cover[u]) ;
        Paint(right(u) , cover[u]) ;
        cover[u] = 0 ;
    }
}

inline void zig(int x) {
	/* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) ;
}

inline void zag(int x) {
	/* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) ;
}

inline void Splay(int x) {
    Clear(x) ;
    for (int y , z ; !Isrt(x) ; ) {
        y = fa[x] , z = fa[y] ;
        if (Isrt(y))
            if(left(y) == x) zig(x) ; else zag(x) ;
        else if(left(z) == y)
            if(left(y) == x) zig(y),zig(x) ; else zag(x),zig(x) ;
        else if(right(y) == x) zag(y),zag(x) ; else zig(x),zag(x) ;
    }
    Maintain(x) ;
}

inline void QUERY(int u , int v) {
	for (int z = null ; v ; v = fa[v] ) {
		Splay(v) ; right(v) = z , z = v ; Maintain(v) ;
	}
	for (v = null ; u ; u = fa[u]) {
    	Splay(u) ;
    	if (!fa[u]) {
			printf("%d\n", d[right(u)]+d[v]+1-(color[u]==lcolor[right(u)])-(color[u]==lcolor[v]) ) ;
            return ;
		}
		right(u) = v , v = u ; Maintain(u) ;
	}
}

inline void CHANGE(int u , int v , int w) {
	for (int z = null ; v ; v = fa[v] ) {
		Splay(v) ; right(v) = z , z = v ; Maintain(v) ;
	}
    for (v = null ; u ; u = fa[u]) {
    	Splay(u) ;
    	if (!fa[u]) {
    		color[u] = w ;
    		Paint(right(u) , w) ;
    		Paint(v , w) ;
		}
		right(u) = v , v = u ; Maintain(u) ;
	}
}

struct FST { int to , next ; } e[maxe] ;
int star[maxn] = {0} , tote = 0 ;

inline void AddEdge(int u , int v) {
    e[++tote].to = v ; e[tote].next = star[u] ; star[u] = tote ;
    e[++tote].to = u ; e[tote].next = star[v] ; star[v] = tote ;
}

inline void BuildTree(int fat , int u) {
    fa[u] = fat ; int p , v ;
    for (p = star[u] ; p ; p = e[p].next ) {
        v = e[p].to ; if (v == fat) continue ;
        BuildTree(u , e[p].to) ;
    }
}

int n , q , i , u , v , w ;

int main() {
//    #define READ
    #ifdef  READ
        freopen(".in" ,"r",stdin ) ;
        freopen(".out","w",stdout) ;
    #endif
    read(n) , read(q) ;
    for (i = 1 ; i <= n ; i ++ ) {
        read(color[i]) ; lcolor[i] = rcolor[i] = color[i] ; d[i] = 1 ;
    }
    for (i = 1 ; i < n ; i ++ ) {
        read(u) , read(v) ; AddEdge(u , v) ;
    }
    BuildTree(null , 1) ;
    while ( q -- ) {
        while (w=getchar() , w<'!') ;
        read(u) , read(v) ;
        if (w == 'Q') QUERY(u , v) ;
        else read(w) , CHANGE(u , v , w) ;
    }
	#ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}

[ZJOI2008]树的统计Count

Posted on 2015年1月17日 17:16
/****************************************\
* Author : ztx
* Title  : [ZJOI2008]树的统计Count
* ALG    : LCT
* CMT    : Link Cut Tree 的经典操作
* Data   :
\****************************************/
/****************************************\
* Author : ztx
* Title  : [ZJOI2008]树的统计Count
* ALG    : LCT
* CMT    : Link Cut Tree 的经典操作
* Data   :
\****************************************/

#include <cstdio>
#include <cstring>

#define  max(a,b)  ((a)>(b)?(a):(b))
#define  infi  0x7f7f7f7fLL

int CH , neg ;
inline void read(int& ret) {
    ret = neg = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') neg = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (neg) ret = -ret ;
}

#define  maxn  300010LL
#define  maxe  600010LL

int fa[maxn] = {0} , ch[maxn][2] = {0} ;
int rev[maxn] = {0} ;
int maxv[maxn] , sumv[maxn] = {0} , val[maxn] = {0} ;

#define  null      0LL
#define  left(u)   ch[u][0]
#define  right(u)  ch[u][1]

template<typename T>inline void Exchange(T&a , T&b) { T c = a ; a = b ; b = c ; }

inline bool Isrt(int u) {
	return (!fa[u]) || ((left(fa[u])!=u)&&(right(fa[u])!=u)) ;
}

inline void Maintain(int u) {
    maxv[u] = sumv[u] = val[u] ;
    if (left(u))  maxv[u] = max(maxv[u] , maxv[left(u)])  , sumv[u] += sumv[left(u)]  ;
    if (right(u)) maxv[u] = max(maxv[u] , maxv[right(u)]) , sumv[u] += sumv[right(u)] ;
}

inline void Clear(int u) {
    if (u && rev[u]) {
        if (left(u))  rev[left(u)]  ^= true ;
        if (right(u)) rev[right(u)] ^= true ;
        Exchange(left(u) , right(u)) ;
        rev[u]  = false ;
    }
}

inline void zig(int x) {
    /* right rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[right(x)] = y ; left(y) = right(x) ; fa[y] = x ; right(x) = y ;
    Maintain(y) ;
}

inline void zag(int x) {
    /* left rotate */
    int y = fa[x] , z = fa[y] ;
    if (left(z) == y) left(z) = x ; else if(right(z) == y) right(z) = x ; fa[x] = z ;
    fa[left(x)] = y ; right(y) = left(x) ; fa[y] = x ; left(x) = y ;
    Maintain(y) ;
}

inline void Splay(int x) {
	Clear(x) ;
	int y , z ;
	while (!Isrt(x)) {
		y = fa[x] , z = fa[y] ;
		if (Isrt(y)) {
			Clear(y) , Clear(x) ;
			if (left(y) == x) zig(x) ; else zag(x) ;
		} else {
			Clear(z) , Clear(y) , Clear(x) ;
			if (left(z) == y) {
				if (left(y) == x) zig(x) , zig(x) ;
				else zag(x) , zig(x) ;
			} else if (right(z) == y) {
				if (right(y) == x) zag(x) , zag(x) ;
				else zig(x) , zag(x) ;
			}
		}
	}
	Maintain(x) ;
}

inline void Access(int u) {
	for (int v = null ; u ; u = fa[u]) Splay(u) , right(u) = v , v = u , Maintain(u) ;
}

inline void MakeRoot(int u) {
	Access(u) , Splay(u) , rev[u] ^= true ;
}

inline void QMAX(int u , int v) {
    MakeRoot(u) ; Access(v) , Splay(v) ;
    printf("%d\n", maxv[v] ) ;
}

inline void QSUM(int u , int v) {
    MakeRoot(u) ; Access(v) , Splay(v) ;
    printf("%d\n", sumv[v] ) ;
}

inline void CHANGE(int u , int v) {
    Splay(u) ; val[u] = v ; Maintain(u) ;
}

struct FST { int to , next ; } e[maxe] ;
int star[maxn] = {0} , tote = 0 ;

inline void AddEdge(int u , int v) {
    e[++tote].to = v ; e[tote].next = star[u] ; star[u] = tote ;
    e[++tote].to = u ; e[tote].next = star[v] ; star[v] = tote ;
}

inline void BuildTree(int tp , int u) {
int p , v ;
    fa[u] = tp ;
    for (p = star[u] ; p ; p = e[p].next ) {
        v = e[p].to ; if (v == tp) continue ;
        BuildTree(u , v) ;
    }
}

int n , q , i , u , v , cmd ;

int main() {
    #define READ
    #ifdef  READ
        freopen("bzoj_1036.in" ,"r",stdin ) ;
        freopen("bzoj_1036.out","w",stdout) ;
    #endif
    read(n) ;
    for (i = 1 ; i < n ; i ++ ) {
        read(u) , read(v) ; AddEdge(u , v) ;
    }
    for (i = 1 ; i <= n ; i ++ )
        read(val[i]) , maxv[i] = sumv[i] = val[i] ;
    BuildTree(null , 1) ;
    read(q) ;
    while ( q -- ) {
        while (CH = getchar() , CH<'!') ;
        while (cmd = CH , CH = getchar() , CH>'!') ;
        read(u) , read(v) ;
        if (cmd == 'X') QMAX(u , v) ;
        if (cmd == 'M') QSUM(u , v) ;
        if (cmd == 'E') CHANGE(u , v) ;
    }

    #ifdef  READ
        fclose(stdin) ; fclose(stdout) ;
    #else
        getchar() ; getchar() ;
    #endif
    return 0 ;
}