BZOJ[3091] 城市旅行

  这个题一看就是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 }
View Code

 

posted @ 2018-03-24 17:43  Nawox  阅读(215)  评论(0编辑  收藏  举报