题目大意:维护一棵树,提供四种操作:
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 ); } } }