题目大意:维护一棵树,提供四种操作:
1.将x到y的路径上所有的点权值+z
2.将x1到y1的边断开,然后将x2和y2链接,数据保证链接后仍然是棵树
3.将x到y的路径上所有的点权值*z
4.询问x到y路径上节点的权值和对51061取模
我就复制粘贴算了为何要重新打一遍
Link-Cut-Tree第一道功能比较全的题,比较水,水个*啊,很久以前就写完了,由于BZ挂了一直没交上去,今天交上去之后从中午开始TLE,一直TLE到现在。。。。
史上第一次除了Hash Killer III之外交完50次。。。一次30s,各种酸爽。。。
之前的写法Move_To_Root之后x上还有标记没管,直接把右子树切了,结果标记传不下去,导致死循环。。。血的教训啊啊啊啊!!谁让我不扒标程各种自己敲。。。代码看了不下20遍。。。各种优化常数,读入优化也加了!深搜改广搜!递归全删了!手写系统栈!取模改成减!各种inline!连scanf都被我缩成getchar了!最后切掉之后硬压到10s以内,蛋疼死了。。。。
不想说啥了,想哭。。。。。算了总算切了 切了就好 以后就好写了
不愧是Link-Cut-Tree,比树链剖分就多出一个Link和一个Cut,难写的也就一个Link和一个Cut。。。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
#define Mo 51061
using namespace std;
typedef unsigned int u;
inline int getc() {
static const int L = 1 << 15;
static char buf[L], *S = buf, *T = buf;
if (S == T) {
T = (S = buf) + fread(buf, 1, L, stdin);
if (S == T)
return EOF;
}
return *S++;
}
inline int getint() {
int c;
while(!isdigit(c = getc()) && c != '-');
bool sign = c == '-';
int tmp = sign ? 0 : c - '0';
while(isdigit(c = getc()))
tmp = (tmp << 1) + (tmp << 3) + c - '0';
return sign ? -tmp : tmp;
}
inline void output(int x)
{
static int a[20];
if (x == 0)
putchar('0');
else {
int top = 0;
if (x < 0)
putchar('-'), x=-x;
while(x) {
a[++top] = x % 10;
x /= 10;
}
for(int i = top; i >= 1; --i)
putchar('0' + a[i]);
}
puts("");
}
struct abcd{
abcd *fa,*ls,*rs;
int siz;
u num,sum;
u add_mark,times_mark;
bool rev_mark;
abcd(int x);
void Push_Down();
void Push_Up();
void times(u x);
void add(u x);
void rev();
}*null=new abcd(0),*tree[M];
abcd :: abcd(int x)
{
fa=ls=rs=null;
if(x) siz=1;
else siz=0;
num=sum=x;
add_mark=0;
times_mark=1;
}
void abcd :: times(u x)
{
if(this==null)
return ;
times_mark*=x;
times_mark%=Mo;
num*=x;
num%=Mo;
add_mark*=x;
add_mark%=Mo;
sum*=x;
sum%=Mo;
}
void abcd :: add(u x)
{
if(this==null)
return ;
num+=x;
num=(num>Mo?num-Mo:num);
add_mark+=x;
add_mark=(add_mark>Mo?add_mark-Mo:add_mark);
sum+=x*siz%Mo;
sum=(sum>Mo?sum-Mo:sum);
}
void abcd :: rev()
{
if(this==null)
return ;
rev_mark^=1;
swap(ls,rs);
}
void abcd :: Push_Up()
{
if(this==null)
return ;
sum=(ls->sum+rs->sum+num)%Mo;
siz=ls->siz+rs->siz+1;
}
void abcd :: Push_Down()
{
//if(fa->ls==this||fa->rs==this)
// fa->Push_Down();
if(this==null)
return ;
if(times_mark^1)
{
ls->times(times_mark);
rs->times(times_mark);
times_mark=1;
}
if(add_mark)
{
ls->add(add_mark);
rs->add(add_mark);
add_mark=0;
}
if(rev_mark)
{
ls->rev();
rs->rev();
rev_mark=0;
}
}
abcd *stack[M];int top;
void Push_Down(abcd *x)
{
for(;x->fa->ls==x||x->fa->rs==x;x=x->fa)
stack[++top]=x;
stack[++top]=x;
while(top)
stack[top--]->Push_Down();
}
inline void Zig(abcd *x)
{
if(x==null)
return ;
abcd *y=x->fa;
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
}
inline void Zag(abcd *x)
{
if(x==null)
return ;
abcd *y=x->fa;
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
}
inline void Splay(abcd *x)
{
if(x==null)
return ;
Push_Down(x);
while( x==x->fa->ls||x==x->fa->rs )
{
abcd *y=x->fa,*z=y->fa;
if( z->ls!=y&&z->rs!=y )
{
if(x==y->ls)
Zig(x);
else
Zag(x);
break;
}
if(z->ls==y)
{
if(y->ls==x)
Zig(y),Zig(x);
else
Zag(x),Zig(x);
}
else
{
if(y->rs==x)
Zag(y),Zag(x);
else
Zig(x),Zag(x);
}
}
x->Push_Up();
}
inline void Access(abcd *x)
{
abcd *y=null;
while(x!=null)
{
Splay(x);
x->rs=y;
x->Push_Up();
y=x;
x=x->fa;
}
}
inline void Move_To_Root(abcd *x)
{
Access(x);
Splay(x);
x->rev();
}
inline void Link(abcd *x,abcd *y)
{
Move_To_Root(x);
x->fa=y;
}
inline void Cut(abcd *x,abcd *y)
{
Move_To_Root(x);
Access(y);
Splay(y);
x->fa=null;
y->ls=null;
y->Push_Up();
}
struct ABCD{
int to,next;
}table[M<<1];
int head[M],tot;
int n,m,fa[M];
inline void add(int x,int y)
{
table[++tot].to=y;
table[tot].next=head[x];
head[x]=tot;
}
int q[M],r,h;
void bfs()
{
int i;
q[++r]=1;
while(r!=h)
{
int x=q[++h];
tree[x]=new abcd(1);
if(fa[x])
tree[x]->fa=tree[ fa[x] ];
for(i=head[x];i;i=table[i].next)
{
if(table[i].to==fa[x])
continue;
fa[table[i].to]=x;
q[++r]=table[i].to;
}
}
}
int main()
{
int i,x,y,z;
char p;
n=getint();m=getint();
for(i=1;i<n;i++)
{
x=getint();y=getint();
add(x,y);
add(y,x);
}
bfs();
for(i=1;i<=m;i++)
{
do{
p=getc();
}while(p==' '||p=='\n'||p=='\r');
if(p=='+')
{
x=getint();y=getint();z=getint();
Move_To_Root(tree[x]);
Access(tree[y]);
Splay(tree[y]);
tree[y]->add(z);
}
else if(p=='-')
{
x=getint();y=getint();
Cut(tree[x],tree[y]);
x=getint();y=getint();
Link(tree[x],tree[y]);
}
else if(p=='*')
{
x=getint();y=getint();z=getint();
Move_To_Root(tree[x]);
Access(tree[y]);
Splay(tree[y]);
tree[y]->times(z);
}
else
{
x=getint();y=getint();
Move_To_Root(tree[x]);
Access(tree[y]);
Splay(tree[y]);
output( tree[y]->sum );
}
}
}