【BZOJ2631】tree Link-Cut-Tree

来源:互联网 发布:六级词汇书推荐知乎 编辑:程序博客网 时间:2024/04/29 13:49

题意就是将BZOJ1798的数列的操作改成了树的操作。大体相似,用 Link -Cut-Tree 维护。

貌似细节不少的样子呢……一定要细心……当年这道题调了好久的说……//其实是我太渣了

update 函数里忘记了加 maintain(x) 的错误 QAQ

同时这也是我写的少数数组版代码之一//数组写成这个样子ch[fa[f]][check(f)]也是真心不爽嗯

下面是我的数组版代码~~

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define mod 51061#define N 100005int n,q,ch[N][2],fa[N],rev[N];unsigned int val[N],size[N],sum[N],mul[N],add[N];inline bool root(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}inline bool check(int x){return ch[fa[x]][1]==x;}void reverse(int x){rev[x]^=1;rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;swap(ch[x][0],ch[x][1]);}void calc(int x,unsigned int y,unsigned int z){val[x]=(val[x]*y+z)%mod;sum[x]=(sum[x]*y+size[x]*z)%mod;mul[x]=(mul[x]*y)%mod;add[x]=(add[x]*y+z)%mod;}void pushdown(int x){if(!root(x))pushdown(fa[x]);if(rev[x])reverse(x);if(ch[x][0]) calc(ch[x][0],mul[x],add[x]);if(ch[x][1]) calc(ch[x][1],mul[x],add[x]);mul[x]=1,add[x]=0;}void maintain(int x){sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%mod;size[x]=(size[ch[x][0]]+size[ch[x][1]]+1)%mod;}void rotate(int x){int f=fa[x],d=!check(x);ch[f][d^1]=ch[x][d]; fa[ch[x][d]]=f; ch[x][d]=f;if(!root(f)) ch[fa[f]][check(f)]=x;fa[x]=fa[f]; fa[f]=x;maintain(f);maintain(x);}void splay(int x){pushdown(x);while(!root(x)){if(!root(fa[x]))check(fa[x])^check(x)?rotate(x):rotate(fa[x]);rotate(x);}}void access(int x){int y=0;while(x) splay(x),ch[x][1]=y,maintain(x),x=fa[y=x];}void makeroot(int x){access(x);splay(x);rev[x]^=1;}void link(int x,int y){makeroot(x);fa[x]=y;}void cut(int x,int y){makeroot(x);access(y);splay(y);ch[y][0]=fa[x]=0;}int main(){cin>>n>>q;for(int i=1;i<=n;i++)val[i]=size[i]=sum[i]=mul[i]=1;for(int x,y,i=1;i<n;i++)scanf("%u%u",&x,&y),link(x,y);while(q--){char ch[5];int u,v,x,y;scanf("%s",ch);if(ch[0]=='+'){scanf("%d%d%d",&u,&v,&x);makeroot(u);access(v);splay(v);calc(v,1,x);}else if(ch[0]=='-'){scanf("%d%d%d%d",&u,&v,&x,&y);cut(u,v);link(x,y);}else if(ch[0]=='*'){scanf("%d%d%d",&u,&v,&x);makeroot(u);access(v);splay(v);calc(v,x,0);}else if(ch[0]=='/'){scanf("%d%d",&u,&v);makeroot(u);access(v);splay(v);printf("%u\n",sum[v]);}}return 0;}


0 0
原创粉丝点击