BZOJ[3091] 城市旅行

Posted Nawox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

 

以上是关于BZOJ[3091] 城市旅行的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ3091: 城市旅行

BZOJ 3091: 城市旅行 [LCT splay 期望]

BZOJ 3091: 城市旅行 lct 期望 splay

BZOJ[3091] 城市旅行

BZOJ3091: 城市旅行

bzoj3091城市旅行 LCT区间合并