1. 程式人生 > >bzoj 2759一個動態樹好題

bzoj 2759一個動態樹好題

nbsp 維護 %d roo clas scanf 父親 printf node

真的是動態樹好題,如果把每個點的父親設成p[x],那麽建出來圖應該是一個環套樹森林,拆掉一條邊,就變成了動態樹,考慮維護什麽,對於LCT上每個節點,維護兩組k和b,一組是他到他父親的,一組是他LCT子樹中深度最深的點到深度最淺的點的父親的k和b,查詢時只需查詢一顆樹中sf到自己的k和b,判斷是否有唯一解,然後再解就可以了。註意不能換根,因為樹的形態是固定的。

技術分享圖片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<iostream>
  4 #include<algorithm>
  5
#include<cmath> 6 #define N 30005 7 #define mod 10007 8 using namespace std; 9 int n,p[N],q; 10 int qp(int a,int b){ 11 int c=1; 12 while(b){ 13 if(b&1)c=c*a%mod; 14 a=a*a%mod;b>>=1; 15 } 16 return c; 17 } 18 struct Node{ 19 Node *ch[2
],*fa,*sf; 20 int k,b,sumk,sumb,id; 21 Node(); 22 void pushup(); 23 void pushdown(); 24 }*null=new Node,tree[N]; 25 Node :: Node (){ 26 ch[0]=ch[1]=fa=sf=null; 27 k=sumk=1;b=sumb=id=0; 28 } 29 void Node :: pushup(){ 30 sumk=k;sumb=b; 31 sumb=(sumk*ch[0
]->sumb%mod+sumb)%mod;sumk=ch[0]->sumk*sumk%mod; 32 sumb=(ch[1]->sumk*sumb%mod+ch[1]->sumb)%mod;sumk=sumk*ch[1]->sumk%mod; 33 } 34 void rotate(Node *x){ 35 Node *y=x->fa,*z=y->fa; 36 int w=y->ch[0]==x; 37 x->ch[w]->fa=y;y->ch[w^1]=x->ch[w]; 38 y->fa=x;x->ch[w]=y; 39 if(z->ch[0]==y)z->ch[0]=x; 40 if(z->ch[1]==y)z->ch[1]=x; 41 x->fa=z; 42 y->pushup();x->pushup(); 43 } 44 bool isroot(Node *x){ 45 return x->fa->ch[0]!=x && x->fa->ch[1]!=x; 46 } 47 void splay(Node *x){ 48 Node *y,*z; 49 while(!isroot(x)){ 50 y=x->fa;z=y->fa; 51 if((z->ch[0]==y&&y->ch[0]==x)||(z->ch[1]==y&&y->ch[1]==x)) 52 rotate(y); 53 rotate(x); 54 } 55 } 56 void access(Node *x){ 57 Node *y=null; 58 while(x!=null){ 59 splay(x); 60 x->ch[1]=y; 61 x->pushup(); 62 y=x;x=x->fa; 63 } 64 } 65 Node * find(Node *x){ 66 access(x);splay(x); 67 while(x->ch[0]!=null)x=x->ch[0]; 68 return x; 69 } 70 void cut(Node *x){ 71 Node *rt=find(x); 72 if(rt==x)x->sf=null; 73 else{ 74 access(x); 75 splay(x); 76 x->ch[0]->fa=null; 77 x->ch[0]=null; 78 x->pushup(); 79 if(find(rt->sf)!=find(rt)){ 80 rt->fa=rt->sf; 81 rt->sf=null; 82 } 83 } 84 } 85 void link(Node *x,Node *f,int k,int b){ 86 x->k=k;x->b=b; 87 if(find(f)==find(x))x->sf=f; 88 else x->fa=f; 89 } 90 int query(Node *x){ 91 Node *rt=find(x),*now=rt->sf; 92 access(now);splay(now); 93 if(now->sumk==1){ 94 if(now->sumb==0)return -2; 95 else return -1; 96 } 97 int ans=(mod-now->sumb)*qp(((now->sumk-1)+mod)%mod,mod-2)%mod; 98 access(x);splay(x); 99 return (ans*x->sumk%mod+x->sumb)%mod; 100 } 101 int main(){ 102 srand(20001101); 103 null->fa=null->ch[0]=null->ch[1]=null->sf=null; 104 scanf("%d",&n); 105 for(int i=1,k,b;i<=n;i++){ 106 tree[i].id=i; 107 scanf("%d%d%d",&k,&p[i],&b); 108 link(&tree[i],&tree[p[i]],k,b); 109 } 110 scanf("%d",&q); 111 char ch[5]; 112 int x,y,z,w; 113 while(q--){ 114 scanf("%s",ch); 115 if(ch[0]==A){ 116 scanf("%d",&x); 117 printf("%d\n",query(&tree[x])); 118 } 119 else{ 120 scanf("%d%d%d%d",&x,&y,&z,&w); 121 cut(&tree[x]);p[x]=z; 122 link(&tree[x],&tree[p[x]],y,w); 123 } 124 } 125 return 0; 126 }
View Code

bzoj 2759一個動態樹好題