题目大意:维护一种树形数据结构,支持以下操作:
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\n",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();
}