zoukankan      html  css  js  c++  java
  • BZOJ 2631 tree 动态树(Link-Cut-Tree)

    题目大意:维护一种树形数据结构。支持下面操作:

    1.树上两点之间的点权值+k。

    2.删除一条边。添加一条边,保证加边之后还是一棵树。

    3.树上两点之间点权值*k。

    4.询问树上两点时间点的权值和。


    思路:利用动态树维护这棵树,lct的裸题。假设不会下传标记的,先去做BZOJ1798,也是这种标记,仅仅只是在线段树上做,比这个要简单很多。

    这个也是我的LCT的第一题,理解起来十分困难啊。。。


    CODE:


    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 100010
    #define MO 51061
    using namespace std;
    
    struct Complex{
    	int size;
    	unsigned int val,sum;
    	Complex *son[2],*father;
    	bool reverse;
    	int m_mark,p_mark;
    
    	bool Check() {
    		return father->son[1] == this;
    	}
    	void Reverse();
    	void Plus(unsigned int c);
    	void Mulitiply(unsigned int c);
    	void PushUp();
    	void PushDown();
    }*tree[MAX],*nil = new Complex();
    
    int cnt,points,asks;
    int head[MAX],total;
    int next[MAX << 1],aim[MAX << 1];
    
    char c[10];
    
    void Pretreatment();
    
    inline Complex *NewComplex(unsigned int val);
    
    inline void Add(int x,int y);
    void DFS(int x,int last);
    
    inline void Splay(Complex *a);
    inline void Rotate(Complex *a,bool dir);
    inline void PushPath(Complex *a); 
    
    inline void Access(Complex *a);
    inline void ToRoot(Complex *a);
    inline void Link(Complex *x,Complex *y);
    inline void Cut(Complex *x,Complex *y);
    
    int main()
    {
    	Pretreatment();
    	cin >> points >> asks;
    	for(int x,y,i = 1;i < points; ++i) {
    		scanf("%d%d",&x,&y);
    		Add(x,y),Add(y,x);
    	}
    	for(int i = 1;i <= points; ++i)
    		tree[i] = NewComplex(1);
    	DFS(1,-1);
    	for(int x,y,z,i = 1;i <= asks; ++i) {
    		scanf("%s%d%d",c,&x,&y);
    		if(c[0] == '+') {
    			scanf("%d",&z);
    			ToRoot(tree[x]);
    			Access(tree[y]);
    			Splay(tree[y]);
    			tree[y]->Plus(z);
    		}
    		else if(c[0] == '-') {
    			Cut(tree[x],tree[y]);
    			scanf("%d%d",&x,&y);
    			Link(tree[x],tree[y]);
    		}
    		else if(c[0] == '*') {
    			scanf("%d",&z);
    			ToRoot(tree[x]);
    			Access(tree[y]);
    			Splay(tree[y]);
    			tree[y]->Mulitiply(z);
    		} 
    		else {
    			ToRoot(tree[x]);
    			Access(tree[y]);
    			Splay(tree[y]);
    			printf("%d
    ",tree[y]->sum);
    		}
    	}
    	return 0;
    }
    
    void Complex:: PushUp()
    {
    	sum = (son[0]->sum + son[1]->sum + val) % MO;
    	size = son[0]->size + son[1]->size + 1;
    }
    
    void Complex:: PushDown()
    {
    	if(m_mark != 1) {
    		son[0]->Mulitiply(m_mark);
    		son[1]->Mulitiply(m_mark);
    		m_mark = 1;
    	}
    	if(p_mark) {
    		son[0]->Plus(p_mark);
    		son[1]->Plus(p_mark);
    		p_mark = 0;
    	}
    	if(reverse) {
    		son[0]->Reverse();
    		son[1]->Reverse();
    		reverse = false;
    	}
    }
    
    void Complex:: Reverse() 
    {
    	reverse ^= 1;
    	swap(son[0],son[1]);
    }
    
    void Complex:: Plus(unsigned int c)
    {
    	if(this == nil)	return ;
    	val = (val + c) % MO;
    	p_mark = (p_mark + c) % MO;
    	sum = (sum + (size * c) % MO) % MO;
    }
    
    void Complex:: Mulitiply(unsigned int c)
    {
    	if(this == nil)	return ;
    	m_mark = (m_mark * c) % MO;
    	val = (val * c) % MO;
    	p_mark = (p_mark * c) % MO;
    	sum = (sum * c) % MO;
    }
    
    inline void Add(int x,int y)
    {
    	next[++total] = head[x];
    	aim[total] = y;
    	head[x] = total;
    }
    
    void Pretreatment()
    {
    	nil->size = 0;
    	nil->son[0] = nil->son[1] = nil->father = nil;
    }
    
    inline Complex *NewComplex(unsigned int val)
    {
    	Complex *re = new Complex();
    	re->val = re->sum = val;
    	re->reverse = false;
    	re->son[0] = re->son[1] = re->father = nil;
    	re->p_mark = 0;
    	re->m_mark = 1;
    	re->size = 1;
    	return re;
    }
    
    void DFS(int x,int last)
    {
    	for(int i = head[x];i;i = next[i]) {
    		if(aim[i] == last)	continue;
    		tree[aim[i]]->father = tree[x];
    		DFS(aim[i],x);
    	}
    }
    
    inline void Splay(Complex *a)
    {
    	PushPath(a);
    	while(a == a->father->son[0] || a == a->father->son[1]) {
    		Complex *p = a->father->father;
    		if(p->son[0] != a->father && p->son[1] != a->father)
    			Rotate(a,!a->Check());
    		else if(!a->father->Check()) {
    			if(!a->Check())
    				Rotate(a->father,true),Rotate(a,true);
    			else	Rotate(a,false),Rotate(a,true);
    		}
    		else {
    			if(a->Check())
    				Rotate(a->father,false),Rotate(a,false);
    			else	Rotate(a,true),Rotate(a,false);
    		}
    	}	
    	a->PushUp();
    }
    
    inline void Rotate(Complex *a,bool dir)
    {
    	Complex *f = a->father;
    	f->son[!dir] = a->son[dir];
    	f->son[!dir]->father = f;
    	a->son[dir] = f;
    	a->father = f->father;
    	if(f->father->son[0] == f || f->father->son[1] == f)
    		f->father->son[f->Check()] = a;
    	f->father = a;
    	f->PushUp();
    }
    
    inline void PushPath(Complex *a)
    {
    	static Complex *stack[MAX];
    	int top = 0;
    	for(;a->father->son[0] == a || a->father->son[1] == a;a = a->father)
    		stack[++top] = a;
    	stack[++top] = a;
    	while(top)
    		stack[top--]->PushDown();
    }
    
    inline void Access(Complex *a)
    {
    	Complex *last = nil;
    	while(a != nil) {
    		Splay(a);
    		a->son[1] = last;
    		a->PushUp();
    		last = a;
    		a = a->father;
    	}
    }
    
    inline void ToRoot(Complex *a)
    {
    	Access(a);
    	Splay(a);
    	a->Reverse();
    }
    
    inline void Link(Complex *x,Complex *y)
    {	
    	ToRoot(x);
    	x->father = y;
    }
    
    inline void Cut(Complex *x,Complex *y)
    {
    	ToRoot(x);
    	Access(y);
    	Splay(y);
    	y->son[0]->father = nil;
    	y->son[0] = nil;
    	y->PushUp();
    }


  • 相关阅读:
    java异常
    Swfmill概述
    AS3中e4x用法纲要
    抽象工厂模式(Abstract Factory)
    动态绑定、抽象类、接口
    Form中Trigger的执行顺序
    Form 中FND_Message的用法总结
    Form属性、内置子程序、触发器、系统变量
    Oracle EBS R12 XML数据表格的Excel脚本报表 PLUS :问题杂烩
    Oralce EBS Alert
  • 原文地址:https://www.cnblogs.com/clnchanpin/p/6915808.html
Copyright © 2011-2022 走看看