BZOJ2631 tree(伍一鸣) LCT 秘制标记
Posted TS_Hugh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ2631 tree(伍一鸣) LCT 秘制标记相关的知识,希望对你有一定的参考价值。
这个题一看就是裸地LCT嘛,但是我wa了好几遍,这秘制标记......
注意事项:I.*对+有贡献 II.先下传*再下传+(因为我们已经维护了+,不能再让*对+产生贡献)III.维护+用到size
#include<cstdio> #include<cstring> #include<iostream> #define MAXN 100005 #define P 51061 using namespace std; inline unsigned int read() { unsigned int sum=0; char ch=getchar(); while(ch<‘0‘||ch>‘9‘)ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) { sum=(sum<<1)+(sum<<3)+ch-‘0‘; ch=getchar(); } return sum; } struct LCT { struct Node { Node *ch[2],*f; unsigned int key,multi,pluss,sum,size; bool rev; void pushup() { sum=(key+ch[0]->sum+ch[1]->sum)%P; size=ch[0]->size+1+ch[1]->size; } }null[MAXN]; void swap(Node *&x,Node *&y) { Node *temp=x; x=y; y=temp; } void pushdown(Node *p) { if(p->rev) { p->ch[0]->rev^=1; p->ch[1]->rev^=1; swap(p->ch[0],p->ch[1]); p->rev=0; } if(p->multi!=1) { p->ch[0]->sum=(p->ch[0]->sum*p->multi)%P; p->ch[0]->key=(p->ch[0]->key*p->multi)%P; p->ch[0]->pluss=(p->ch[0]->pluss*p->multi)%P; p->ch[0]->multi=(p->ch[0]->multi*p->multi)%P; p->ch[1]->sum=(p->ch[1]->sum*p->multi)%P; p->ch[1]->key=(p->ch[1]->key*p->multi)%P; p->ch[1]->pluss=(p->ch[1]->pluss*p->multi)%P; p->ch[1]->multi=(p->ch[1]->multi*p->multi)%P; p->multi=1; } if(p->pluss) { if(p->ch[1]!=null) { p->ch[1]->sum=(p->ch[1]->sum+p->pluss*p->ch[1]->size)%P; p->ch[1]->key=(p->ch[1]->key+p->pluss)%P; p->ch[1]->pluss=(p->ch[1]->pluss+p->pluss)%P; } if(p->ch[0]!=null) { p->ch[0]->sum=(p->ch[0]->sum+p->pluss*p->ch[0]->size)%P; p->ch[0]->key=(p->ch[0]->key+p->pluss)%P; p->ch[0]->pluss=(p->ch[0]->pluss+p->pluss)%P; } p->pluss=0; } } void Init() { null->ch[1]=null->ch[0]=null->f=null; for(unsigned int i=1;i<MAXN;i++) null[i].ch[0]=null[i].ch[1]=null[i].f=null,null[i].sum=null[i].key=null[i].multi=1,null[i].pluss=0; } bool isroot(Node *p) { return p->f->ch[0]!=p&&p->f->ch[1]!=p; } unsigned int get(Node *p) { return p->f->ch[1]==p; } void rotate(Node *p) { Node *fa=p->f,*pa=fa->f; unsigned int j=get(p); if(!isroot(fa))pa->ch[get(fa)]=p; if((fa->ch[j]=p->ch[j^1])!=null)fa->ch[j]->f=fa; fa->f=p; p->f=pa; p->ch[j^1]=fa; fa->pushup(); p->pushup(); } void spaly(Node *p) { pushdown(p); for(Node *fa=p->f;!isroot(p);rotate(p),fa=p->f) if(!isroot(fa)) { pushdown(fa->f),pushdown(fa),pushdown(p); rotate(get(fa)==get(p)?fa:p); } else pushdown(fa),pushdown(p); } void expose(Node *x) { Node *y=null; while(x!=null) { spaly(x); x->ch[1]=y; x->pushup(); y=x; x=x->f; } } void make_root(Node *p) { expose(p); spaly(p); p->rev^=1; } void cut(unsigned int a,unsigned int b) { Node *x=null+a,*y=null+b; make_root(x); expose(y); spaly(y); y->ch[0]->f=null; y->ch[0]=null; y->pushup(); } void link(unsigned int a,unsigned int b) { Node *x=null+a,*y=null+b; make_root(x); x->f=y; } void up(unsigned int a,unsigned int b,unsigned int c) { Node *x=null+a,*y=null+b; make_root(x); expose(y); spaly(y); y->pluss=(y->pluss+c)%P; y->key=(y->key+c)%P; y->sum=(y->sum+y->size*c)%P; } void UUP(unsigned int a,unsigned int b,unsigned int c) { Node *x=null+a,*y=null+b; make_root(x); expose(y); spaly(y); y->multi=(y->multi*c)%P; y->key=(y->key*c)%P; y->sum=(y->sum*c)%P; y->pluss=(y->pluss*c)%P; } unsigned int query(unsigned int a,unsigned int b) { Node *x=null+a,*y=null+b; make_root(x); expose(y); spaly(y); return y->sum; } }YY; int main() { YY.Init(); unsigned int n=read(),m=read(); for(unsigned int i=1;i<n;i++) { unsigned int x=read(),y=read(); YY.link(x,y); } for(unsigned int i=1,x,y,z,a,b;i<=m;i++) { char ch; cin>>ch; x=read(),y=read(); switch(ch) { case ‘*‘:z=read(); YY.UUP(x,y,z); break; case ‘+‘:z=read(); YY.up(x,y,z); break; case ‘-‘:a=read(),b=read(); YY.cut(x,y); YY.link(a,b); break; case ‘/‘:printf("%d\n",YY.query(x,y)); break; } } return 0; }
以上是关于BZOJ2631 tree(伍一鸣) LCT 秘制标记的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2631 tree 动态树(Link-Cut-Tree)