这个题一看就是LCT,但是怎么维护呢?
考虑每一组询问的分母就是(n+1)*n/2,然后在然后看一看左子树并到整个子树之后的变化就可以知道我们维护一个lsum: (1*a[1]+2*a[2]+3*a[3]....), 那么lsum*(rsize+1)就是左子树在新字数中多出来的贡献,右子树也是类似的,
然后我们维护这个东西,就好了。
具体来数LCT要维护size,val,sum,lsum,rsum,mark_add,mark_rev就好了
还有个数学个公式会用到,1*n+2*(n-1)+3*(n-2)+....+(n-1)*2+1*n=n*(n+1)*(n+1)/6
1 #include <cmath> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 typedef long long LL; 9 const int maxn=50010; 10 int timer; 11 int read(){ 12 int x=0,fg=1; char c=getchar(); 13 while(c<‘0‘ || c>‘9‘){if(c==‘-‘) fg=-1; c=getchar();} 14 while(c>=‘0‘&&c<=‘9‘){x = x*10 + c-‘0‘; c=getchar();} 15 return x*fg; 16 } 17 int n,m; 18 struct Node{ 19 Node *ch[2],*f; 20 LL lsum,rsum,sum,val,rev,add,size,exp,id; 21 void revs(){ rev^=1; swap(lsum,rsum);} 22 void Set(LL x){ 23 val+=x; add+=x; 24 sum+=size*x; 25 lsum+=x*(1+size)*size/2; 26 rsum+=x*(1+size)*size/2; 27 exp+=x*size*(size+1)*(size+2)/6; 28 } 29 void pushdown(){ 30 if(rev!=0){ 31 ch[0]->revs(); ch[1]->revs(); 32 swap(ch[0],ch[1]); 33 rev=0; 34 } 35 if(add!=0){ 36 ch[0]->Set(add); ch[1]->Set(add); 37 add=0; 38 } 39 return; 40 } 41 void pushup(){ 42 sum=val+ch[0]->sum+ch[1]->sum; 43 int lsize=ch[0]->size,rsize=ch[1]->size; 44 size=1+lsize+rsize; 45 lsum=ch[0]->lsum+val*(lsize+1)+ch[1]->lsum+ch[1]->sum*(lsize+1); 46 rsum=ch[1]->rsum+val*(rsize+1)+ch[0]->rsum+ch[0]->sum*(rsize+1); 47 exp=ch[0]->exp+ch[1]->exp+ch[0]->lsum*(rsize+1)+ch[1]->rsum*(lsize+1)+(lsize+1)*(rsize+1)*val; 48 } 49 void O(){ 50 printf(" id= %lld fa= %lld ch=<%lld,%lld> val= %lld size= %lld sum= %lld lsum= %lld rsum= %lld\n",id,f->id,ch[0]->id,ch[1]->id,val,size,sum,lsum,rsum); 51 } 52 void beg(int); 53 }null[maxn]; 54 void see(string s){ 55 cout<<"see:: "<<s<<endl; 56 bool ok=1; 57 while(ok){ ok=0; for(int i=1;i<=n;i++) if(null[i].rev){null[i].pushdown(); ok=1;}} 58 for(int i=1;i<=n;i++){ 59 null[i].O(); 60 } 61 } 62 void Node:: beg(int x){ 63 ch[0]=ch[1]=f=null; id=x; 64 size=1; val=sum=lsum=rsum=read(); 65 } 66 bool isroot(Node *x){return x!=x->f->ch[0] && x!=x->f->ch[1];} 67 int Get(Node *x){return x==x->f->ch[1];} 68 void rotate(Node *x){ 69 Node *fa=x->f,*pa=fa->f; 70 int j=Get(x); 71 if(!isroot(fa)) pa->ch[Get(fa)]=x; 72 if((fa->ch[j]=x->ch[j^1])!=null) fa->ch[j]->f=fa; 73 x->ch[j^1]=fa; x->f=pa; fa->f=x; 74 fa->pushup(); x->pushup(); 75 } 76 void splay(Node *x){ 77 x->pushdown(); 78 for(Node *fa=x->f;!isroot(x);rotate(x),fa=x->f){ 79 if(!isroot(fa)){ 80 fa->f->pushdown(); fa->pushdown(); x->pushdown(); 81 rotate(Get(fa)==Get(x)? fa:x); 82 } 83 else fa->pushdown(),x->pushdown(); 84 } 85 } 86 void expose(Node *x){ 87 Node *y=null; 88 while(x!=null){ 89 splay(x); 90 x->ch[1]=y; 91 x->pushup(); 92 y=x; x=x->f; 93 } 94 } 95 Node* find_root(Node* x){ 96 while(x->f!=null) x=x->f; 97 return x; 98 } 99 void make_root(Node *x){ 100 expose(x); splay(x); x->revs(); 101 } 102 void link(Node *x,Node *y){ 103 if(x->id==y->id || find_root(x)==find_root(y)) return; 104 make_root(x); expose(y); splay(y); 105 x->f=y; 106 } 107 void cut(Node *x,Node *y){ 108 if(x->id==y->id || find_root(x)!=find_root(y)) return; 109 make_root(y); expose(x); splay(x); 110 x->ch[0]->f=null; 111 x->ch[0]=null; 112 x->pushup(); 113 } 114 void Add(Node *x,Node *y,int d){ 115 if(find_root(x)!=find_root(y)) return; 116 make_root(x); expose(y); splay(y); 117 y->Set(d); 118 } 119 LL GCD(LL a,LL b){ 120 if(b==0) return a; 121 return GCD(b,a%b); 122 } 123 void query(Node *x,Node *y){ 124 if(find_root(x)!=find_root(y)){printf("-1\n"); return;} 125 make_root(x); 126 expose(y); 127 splay(y); 128 int size=y->size; 129 LL a=y->exp,b=(1+size)*size/2; 130 LL gcd=GCD(a,b); 131 a/=gcd; b/=gcd; 132 printf("%lld/%lld\n",a,b); 133 } 134 int main(){ 135 // freopen("a.in","r",stdin); 136 // freopen("1.out","w",stdout); 137 n=read(); m=read(); 138 null->ch[0]=null->ch[1]=null->f=null; 139 for(int i=1;i<=n;i++) null[i].beg(i); 140 int x,y; 141 for(int i=1;i<n;i++){ 142 x=read(); y=read(); 143 link(null+x,null+y); 144 } 145 int opt,d; 146 for(int i=1;i<=m;i++){ 147 opt=read(); x=read(); y=read(); 148 if(opt==1) cut(null+x,null+y); 149 if(opt==2) link(null+x,null+y); 150 if(opt==3) d=read(),Add(null+x,null+y,d); 151 if(opt==4) query(null+x,null+y); 152 } 153 }