zoukankan      html  css  js  c++  java
  • 洛谷 P1501 [国家集训队]Tree II

    看来这个LCT板子并没有什么问题

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 typedef long long LL;
      5 const LL md=51061;
      6 namespace LCT
      7 {
      8 struct Node
      9 {
     10     Node *ch[2],*fa;
     11     bool rev;
     12     LL addv,mulv;
     13     LL dat,sum,sz;
     14     void padd(LL x)
     15     {
     16         addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md;
     17     }
     18     void pmul(LL x)
     19     {
     20         addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md;
     21     }
     22     void upd()
     23     {
     24         sum=((ch[0]?ch[0]->sum:0)+(ch[1]?ch[1]->sum:0)+dat)%md;
     25         sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1;
     26     }
     27     void pd()
     28     {
     29         if(rev)
     30         {
     31             swap(ch[0],ch[1]);
     32             if(ch[0])    ch[0]->rev^=1;
     33             if(ch[1])    ch[1]->rev^=1;
     34             rev=0;
     35         }
     36         if(mulv!=1)
     37         {
     38             if(ch[0])    ch[0]->pmul(mulv);
     39             if(ch[1])    ch[1]->pmul(mulv);
     40             mulv=1;
     41         }
     42         if(addv)
     43         {
     44             if(ch[0])    ch[0]->padd(addv);
     45             if(ch[1])    ch[1]->padd(addv);
     46             addv=0;
     47         }
     48     }
     49 }nodes[300100];
     50 LL mem;
     51 Node *getnode()
     52 {
     53     return nodes+(mem++);
     54 }
     55 bool isroot(Node *x)
     56 {
     57     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
     58 }
     59 bool gson(Node *o)    {return o==o->fa->ch[1];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲
     60 void rotate(Node *o,bool d)
     61 //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d)
     62 {
     63     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会
     64     o->ch[!d]=k->ch[d];k->ch[d]=o;
     65     o->upd();k->upd();
     66     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
     67 }
     68 Node *st[300100];LL top;
     69 void solvetag(Node *o)
     70 {
     71     while(!isroot(o))    st[++top]=o,o=o->fa;
     72     st[++top]=o;
     73     while(top)    st[top--]->pd();
     74 }
     75 void splay(Node *o)
     76 {
     77     solvetag(o);
     78     Node *fa,*fafa;bool d1,d2;
     79     while(!isroot(o))
     80     {
     81         fa=o->fa;d1=(o==fa->ch[0]);
     82         if(isroot(fa))    rotate(fa,d1);
     83         else
     84         {
     85             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保证fa不是root之后才能获取这两个值,曾错过
     86             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
     87             else    rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
     88         }
     89     }
     90 }
     91 void access(Node *o)
     92 {
     93     for(Node *lst=NULL;o;lst=o,o=o->fa)
     94     {
     95         splay(o);//此处不pushdown是由于splay中保证进行过了
     96         o->ch[1]=lst;o->upd();//注意upd
     97     }
     98 }
     99 Node *gtop(Node *o)
    100 {
    101     access(o);splay(o);
    102     for(;o->ch[0];o=o->ch[0],o->pd());//此处不在开始前pushdown(o)是由于splay中保证进行过了
    103     splay(o);return o;//听说这里不splay一下也很难卡掉
    104 }
    105 void mtop(Node *o)    {access(o);splay(o);o->rev^=1;}
    106 void link(Node *x,Node *y)
    107 {
    108     if(gtop(x)==gtop(y))    return;
    109     mtop(y);y->fa=x;
    110 }
    111 void cut(Node *x,Node *y)
    112 {
    113     mtop(x);access(y);splay(y);
    114     if(y->ch[0]!=x||x->ch[1])    return;//如果x、y之间直接有边,那么上面一行的操作之后应当是x与y在单独一棵splay中,那么一定保证y左子节点是x且x没有右子节点
    115     x->fa=y->ch[0]=NULL;//注意,改的是x的父亲和y的子节点(虽然x的确是树的根,但是此时在splay上是y的子节点,不能搞混)
    116     y->upd();//注意
    117 }
    118 LL query(Node *x,Node *y)
    119 {
    120     mtop(x);access(y);splay(y);
    121     //if(gtop(y)!=x)    return 0;//此题保证x与y连通,不需要
    122     return y->sum;
    123 }
    124 void add(Node *x,Node *y,LL t)
    125 {
    126     mtop(x);access(y);splay(y);
    127     y->padd(t);
    128 }
    129 void mul(Node *x,Node *y,LL t)
    130 {
    131     mtop(x);access(y);splay(y);
    132     y->pmul(t);
    133 }
    134 }
    135 LCT::Node *nd[300100];
    136 LL n,q;char tmp[20];
    137 int main()
    138 {
    139     LL i,x,y,t,x2,y2;
    140     scanf("%lld%lld",&n,&q);
    141     for(i=1;i<=n;i++)
    142     {
    143         nd[i]=LCT::getnode();
    144         nd[i]->mulv=1;nd[i]->dat=nd[i]->sum=1;nd[i]->sz=1;
    145     }
    146     for(i=1;i<n;i++)
    147     {
    148         scanf("%lld%lld",&x,&y);
    149         LCT::link(nd[x],nd[y]);
    150     }
    151     while(q--)
    152     {
    153         scanf("%s",tmp);
    154         switch(tmp[0])
    155         {
    156         case '+':
    157             scanf("%lld%lld%lld",&x,&y,&t);
    158             LCT::add(nd[x],nd[y],t);
    159             break;
    160         case '-':
    161             scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2);
    162             LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
    163             break;
    164         case '*':
    165             scanf("%lld%lld%lld",&x,&y,&t);
    166             LCT::mul(nd[x],nd[y],t);
    167             break;
    168         case '/':
    169             scanf("%lld%lld",&x,&y);
    170             printf("%lld
    ",LCT::query(nd[x],nd[y]));
    171         }
    172     }
    173     return 0;
    174 }

    压行后:

      1 #pragma GCC optimize("Ofast")
      2 #pragma GCC optimize("inline","fast-math","unroll-loops","no-stack-protector")
      3 #pragma GCC diagnostic error "-fwhole-program"
      4 #pragma GCC diagnostic error "-fcse-skip-blocks"
      5 #pragma GCC diagnostic error "-funsafe-loop-optimizations"
      6 #pragma GCC diagnostic error "-std=c++14"
      7 #include<cstdio>
      8 #include<algorithm>
      9 using namespace std;
     10 typedef long long LL;
     11 const LL md=51061;
     12 namespace LCT
     13 {
     14 struct Node
     15 {
     16     Node *ch[2],*fa;
     17     bool rev;
     18     LL addv,mulv;
     19     LL dat,sum,sz;
     20     void padd(LL x)
     21     {
     22         addv=(addv+x)%md;dat=(dat+x)%md;sum=(sum+x*sz)%md;
     23     }
     24     void pmul(LL x)
     25     {
     26         addv=addv*x%md;mulv=mulv*x%md;dat=dat*x%md;sum=sum*x%md;
     27     }
     28     void upd()
     29     {
     30         sum=((ch[0]?ch[0]->sum:0)+(ch[1]?ch[1]->sum:0)+dat)%md;
     31         sz=(ch[0]?ch[0]->sz:0)+(ch[1]?ch[1]->sz:0)+1;
     32     }
     33     void pd()
     34     {
     35         if(rev)
     36         {
     37             swap(ch[0],ch[1]);
     38             if(ch[0])    ch[0]->rev^=1;
     39             if(ch[1])    ch[1]->rev^=1;
     40             rev=0;
     41         }
     42         if(mulv!=1)
     43         {
     44             if(ch[0])    ch[0]->pmul(mulv);
     45             if(ch[1])    ch[1]->pmul(mulv);
     46             mulv=1;
     47         }
     48         if(addv)
     49         {
     50             if(ch[0])    ch[0]->padd(addv);
     51             if(ch[1])    ch[1]->padd(addv);
     52             addv=0;
     53         }
     54     }
     55 }nodes[300100];
     56 LL mem;
     57 Node *getnode()
     58 {
     59     return nodes+(mem++);
     60 }
     61 bool isroot(Node *x)
     62 {
     63     return (!x->fa)||((x->fa->ch[0]!=x)&&(x->fa->ch[1]!=x));
     64 }
     65 bool gson(Node *o)    {return o==o->fa->ch[1];}//获得是父亲的左儿子(返回0)还是右儿子(1),要求保证存在父亲
     66 void rotate(Node *o,bool d)
     67 //在o子树中执行d=0左旋,d=1右旋,在旋转前不标记下传,并将o父节点的对应子节点由o变为需要值,要求保证存在子树(!d)
     68 {
     69     Node *k=o->ch[!d];if(!isroot(o))    o->fa->ch[gson(o)]=k;//注意这一句修改o父节点的要写在前面,曾经出过错调了一会
     70     o->ch[!d]=k->ch[d];k->ch[d]=o;
     71     o->upd();k->upd();
     72     k->fa=o->fa;o->fa=k;if(o->ch[!d])    o->ch[!d]->fa=o;
     73 }
     74 Node *st[300100];LL top;
     75 void solvetag(Node *o)
     76 {
     77     while(!isroot(o))    st[++top]=o,o=o->fa;
     78     st[++top]=o;
     79     while(top)    st[top--]->pd();
     80 }
     81 void splay(Node *o)
     82 {
     83     solvetag(o);
     84     Node *fa,*fafa;bool d1,d2;
     85     while(!isroot(o))
     86     {
     87         fa=o->fa;d1=(o==fa->ch[0]);
     88         if(isroot(fa))    rotate(fa,d1);
     89         else
     90         {
     91             fafa=o->fa->fa;d2=(fa==fafa->ch[0]);//要保证fa不是root之后才能获取这两个值,曾错过
     92             if(d1==d2)    rotate(fafa,d1),rotate(fa,d1);//zig-zig,两次相同方向的单旋,先把父亲转上去,再把自己转上去
     93             else    rotate(fa,d1),rotate(fafa,d2);//zig-zag,两次相反方向的单旋,连续两次把自己转上去
     94         }
     95     }
     96 }
     97 void access(Node *o)
     98 {
     99     for(Node *lst=NULL;o;lst=o,o=o->fa)
    100     {
    101         splay(o);
    102         o->ch[1]=lst;o->upd();
    103     }
    104 }
    105 Node *gtop(Node *o)
    106 {
    107     access(o);splay(o);
    108     for(;o->ch[0];o=o->ch[0],o->pd());
    109     splay(o);return o;
    110 }
    111 void mtop(Node *o)                {access(o);splay(o);o->rev^=1;}
    112 void split(Node *x,Node *y)        {mtop(x);access(y);splay(y);}
    113 void link(Node *x,Node *y)        {mtop(y);y->fa=x;}
    114 void cut(Node *x,Node *y)        {split(x,y);x->fa=y->ch[0]=NULL;y->upd();}
    115 LL query(Node *x,Node *y)        {split(x,y);return y->sum;}
    116 void add(Node *x,Node *y,LL t)    {split(x,y);y->padd(t);}
    117 void mul(Node *x,Node *y,LL t)    {split(x,y);y->pmul(t);}
    118 }
    119 LCT::Node *nd[300100];
    120 LL n,q;char tmp[20];
    121 int main()
    122 {
    123     LL i,x,y,t,x2,y2;
    124     scanf("%lld%lld",&n,&q);
    125     for(i=1;i<=n;i++)
    126     {
    127         nd[i]=LCT::getnode();
    128         nd[i]->mulv=1;nd[i]->dat=nd[i]->sum=1;nd[i]->sz=1;
    129     }
    130     for(i=1;i<n;i++)
    131     {
    132         scanf("%lld%lld",&x,&y);
    133         LCT::link(nd[x],nd[y]);
    134     }
    135     while(q--)
    136     {
    137         scanf("%s",tmp);
    138         switch(tmp[0])
    139         {
    140         case '+':
    141             scanf("%lld%lld%lld",&x,&y,&t);
    142             LCT::add(nd[x],nd[y],t);
    143             break;
    144         case '-':
    145             scanf("%lld%lld%lld%lld",&x,&y,&x2,&y2);
    146             LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
    147             break;
    148         case '*':
    149             scanf("%lld%lld%lld",&x,&y,&t);
    150             LCT::mul(nd[x],nd[y],t);
    151             break;
    152         case '/':
    153             scanf("%lld%lld",&x,&y);
    154             printf("%lld
    ",LCT::query(nd[x],nd[y]));
    155         }
    156     }
    157     return 0;
    158 }
    View Code

    重新打了一个板子

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cassert>
      4 #define md 51061
      5 using namespace std;
      6 typedef long long LL;
      7 int Add(int a,int b)    {return (a+b)%md;}
      8 int Add(int a,int b,int c)    {return (a+b+c)%md;}
      9 int Mul(int a,int b)    {return LL(a)*b%md;}
     10 namespace LCT
     11 {
     12 const int N=100000;
     13 struct Node
     14 {
     15     Node *ch[2],*fa;
     16     bool rev;
     17     int addv,mulv;
     18     int dat,sum,sz;
     19     void upd()
     20     {
     21         sum=Add((ch[0]?ch[0]->sum:0),dat,(ch[1]?ch[1]->sum:0));
     22         sz=(ch[0]?ch[0]->sz:0)+1+(ch[1]?ch[1]->sz:0);
     23     }
     24     void padd(int x)    {addv=Add(addv,x);dat=Add(dat,x);sum=Add(sum,Mul(x,sz));}
     25     void pmul(int x)    {addv=Mul(addv,x);mulv=Mul(mulv,x);dat=Mul(dat,x);sum=Mul(sum,x);}
     26     void pd()
     27     {
     28         if(rev)
     29         {
     30             swap(ch[0],ch[1]);
     31             if(ch[0])    ch[0]->rev^=1;
     32             if(ch[1])    ch[1]->rev^=1;
     33             rev=0;
     34         }
     35         if(mulv!=1)
     36         {
     37             if(ch[0])    ch[0]->pmul(mulv);
     38             if(ch[1])    ch[1]->pmul(mulv);
     39             mulv=1;
     40         }
     41         if(addv)
     42         {
     43             if(ch[0])    ch[0]->padd(addv);
     44             if(ch[1])    ch[1]->padd(addv);
     45             addv=0;
     46         }
     47     }
     48     bool isroot()    {return (!fa)||(this!=fa->ch[0]&&this!=fa->ch[1]);}
     49     bool gson()    {return this==fa->ch[1];}
     50     void rot()//将自身向上旋,要求已经完成下传标记
     51     {
     52         bool d=gson();Node *f=fa;
     53         fa=f->fa;if(!f->isroot())    f->fa->ch[f->gson()]=this;
     54         f->ch[d]=ch[!d];if(ch[!d])    ch[!d]->fa=f;
     55         f->fa=this;ch[!d]=f;
     56         f->upd();upd();
     57     }
     58 }nodes[N+100];
     59 Node *st[N+100];int top;
     60 int mem;
     61 Node *getnode()
     62 {
     63     Node *t=nodes+mem++;t->mulv=1;t->sz=1;t->dat=t->sum=1;
     64     return t;
     65 }
     66 void solvetag(Node *o)
     67 {
     68     while(!o->isroot())    st[++top]=o,o=o->fa;
     69     st[++top]=o;
     70     while(top)    st[top--]->pd();
     71 }
     72 void splay(Node *o)
     73 {
     74     solvetag(o);
     75     for(;!o->isroot();o->rot())
     76         if(!o->fa->isroot())
     77             o->gson()==o->fa->gson()?o->fa->rot():o->rot();
     78 }
     79 void acc(Node *o)
     80 {
     81     for(Node *lst=0;o;lst=o,o=o->fa)
     82         splay(o),o->ch[1]=lst,o->upd();
     83 }
     84 void mtop(Node *o)    {acc(o);splay(o);o->rev^=1;}
     85 void link(Node *x,Node *y)    {mtop(y);y->fa=x;}
     86 void cut(Node *x,Node *y)    {mtop(x);acc(y);splay(y);x->fa=y->ch[0]=0;y->upd();}
     87 int query(Node *x,Node *y)    {mtop(x);acc(y);splay(y);return y->sum;}
     88 void add(Node *x,Node *y,int t)    {mtop(x);acc(y);splay(y);y->padd(t);}
     89 void mul(Node *x,Node *y,int t)    {mtop(x);acc(y);splay(y);y->pmul(t);}
     90 }
     91 LCT::Node *nd[100100];
     92 int n,q;char tmp[20];
     93 int main()
     94 {
     95     int i,x,y,t,x2,y2;
     96     scanf("%d%d",&n,&q);
     97     for(i=1;i<=n;i++)    nd[i]=LCT::getnode();
     98     for(i=1;i<n;i++)
     99     {
    100         scanf("%d%d",&x,&y);
    101         LCT::link(nd[x],nd[y]);
    102     }
    103     while(q--)
    104     {
    105         scanf("%s",tmp);
    106         switch(tmp[0])
    107         {
    108         case '+':
    109             scanf("%d%d%d",&x,&y,&t);
    110             LCT::add(nd[x],nd[y],t);
    111             break;
    112         case '-':
    113             scanf("%d%d%d%d",&x,&y,&x2,&y2);
    114             LCT::cut(nd[x],nd[y]);LCT::link(nd[x2],nd[y2]);
    115             break;
    116         case '*':
    117             scanf("%d%d%d",&x,&y,&t);
    118             LCT::mul(nd[x],nd[y],t);
    119             break;
    120         case '/':
    121             scanf("%d%d",&x,&y);
    122             printf("%d
    ",LCT::query(nd[x],nd[y]));
    123         }
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    Prometheus监控神器-服务发现篇(二)
    Prometheus监控神器-服务发现篇(一)
    Prometheus监控神器-Alertmanager篇(4)
    Prometheus监控神器-Alertmanager篇(3)
    Prometheus监控神器-Rules篇
    Linux内核分析——字符集总结与分析
    Linux内核分析——ELF文件格式分析
    Linux内核分析——程序破解
    Linux内核学习总结
    《Linux内核设计与实现》课本第四章学习总结
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8877033.html
Copyright © 2011-2022 走看看