码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2759一个动态树好题

时间:2018-01-06 14:10:33      阅读:150      评论:0      收藏:0      [点我收藏+]

标签:森林   一个   zoj   i++   find   and   class   图片   hup   

真的是动态树好题,如果把每个点的父亲设成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一个动态树好题

标签:森林   一个   zoj   i++   find   and   class   图片   hup   

原文地址:https://www.cnblogs.com/Ren-Ivan/p/8213563.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!