1. 程式人生 > >BZOJ[3091] 城市旅行

BZOJ[3091] 城市旅行

bool bsp struct code pri lap size swa lld

  這個題一看就是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] 城市旅行