BZOJ 2631 tree LCT

来源:互联网 发布:树洞外链美化源码 编辑:程序博客网 时间:2024/05/16 04:36

题目大意:给定一棵结点初始值为1的无根树,要求支持以下操作:链加,链乘,链求和,断一条边连一条边保证还是一棵树

真·LCT模板题,标记最好是直接推给儿子(也就是标记跟自己没关系),推标记要先推乘后推加。
反转时不能直接把标记变成false
在Splay之前要调用To_pushdown(即把点o的祖先的标记都推下来)

#include <cstdio>#include <algorithm>#define N 100005#define MOD 51061using namespace std;#define int long longstruct Node {    Node *ch[2],*pa;    int s,val,sum,add_mark,times_mark;    bool rev_mark;    int dir() {return pa->ch[0]==this ? 0 : pa->ch[1]==this ? 1 : -1;}    Node();    void pushdown();    void maintain();    void add(int x);    void rev();    void times(int x);}*null=new Node(),p[N];Node :: Node() {    s=null ? 1 : 0;    val=sum=s;    ch[0]=ch[1]=pa=null;    add_mark=0;    times_mark=1;    rev_mark=false;}void Node :: pushdown() {    if(this==null) return ;    if(times_mark!=1) {        ch[0]->times(times_mark);        ch[1]->times(times_mark);        times_mark=1;    }    if(add_mark) {        ch[0]->add(add_mark);        ch[1]->add(add_mark);        add_mark=0;    }    if(rev_mark) {        ch[0]->rev();        ch[1]->rev();        rev_mark=false;    }    return ;}void Node :: maintain() {    if(this==null) return ;    s=ch[0]->s+ch[1]->s+1;    sum=(ch[0]->sum+ch[1]->sum+val)%MOD;    return ;}void Node :: add(int x) {    if(this==null) return ;    val=(val+x)%MOD;    add_mark=(add_mark+x)%MOD;    sum=(sum+x*s)%MOD;    return ;}void Node :: times(int x) {    if(this==null) return ;    times_mark=(times_mark*x)%MOD;    val=(val*x)%MOD;    sum=(sum*x)%MOD;    add_mark=(add_mark*x)%MOD;    return ;}void Node :: rev() {    if(this==null) return ;    rev_mark=!rev_mark;    swap(ch[0],ch[1]);    return ;}void To_pushdown(Node* o) {    if(~(o->dir())) To_pushdown(o->pa);    o->pushdown();    return ;}void Rotate(Node* o,int d) {    Node* k=o->ch[d^1]; int d2;    o->ch[d^1]=k->ch[d]; k->ch[d]->pa=o;    k->ch[d]=o;    o->maintain(); k->maintain();    if(~(d2=o->dir())) o->pa->ch[d2]=k;    k->pa=o->pa; o->pa=k;    return ;}void Splay(Node* o) {    int d; To_pushdown(o);    while(~(d=o->dir())) {        if(d==o->pa->dir()) Rotate(o->pa->pa,d^1);        Rotate(o->pa,d^1);    }    return ;}void Access(Node* o) {    Node* p=null;    while(o!=null) {        Splay(o);        o->ch[1]=p; o->maintain();        p=o;        o=o->pa;    }    return ;}void Move_to_root(Node* o) {    Access(o); Splay(o);    o->rev();    return ;}void Link(Node* x,Node* y) {    Move_to_root(x);    x->pa=y;    return ;}void Cut(Node* x,Node* y) {    Move_to_root(x);    Access(y); Splay(y);    y->ch[0]=null; y->maintain();    x->pa=null;    return ;} main() {    int n,m;    scanf("%lld%lld",&n,&m);    for(int i=1;i<n;i++) {        int x,y;        scanf("%lld%lld",&x,&y);        Link(&p[x],&p[y]);    }    while(m--) {        char mode[2];        scanf("%s",mode);        if(mode[0]=='+') {            int x,y,z;            scanf("%lld%lld%lld",&x,&y,&z);            Move_to_root(&p[x]);            Access(&p[y]); Splay(&p[y]);            p[y].add(z);        }        if(mode[0]=='-') {            int x,y;            scanf("%lld%lld",&x,&y);            Cut(&p[x],&p[y]);            scanf("%lld%lld",&x,&y);            Link(&p[x],&p[y]);        }        if(mode[0]=='*') {            int x,y,z;            scanf("%lld%lld%lld",&x,&y,&z);            Move_to_root(&p[x]);            Access(&p[y]); Splay(&p[y]);            p[y].times(z);        }        if(mode[0]=='/') {            int x,y;            scanf("%lld%lld",&x,&y);            Move_to_root(&p[x]);            Access(&p[y]); Splay(&p[y]);            printf("%lld\n",p[y].sum%MOD);        }    }    return 0;}
0 0
原创粉丝点击