BZOJ4530 [BJOI2014]大融合(LCT)

题目描述

小强要在N个孤立的星球上建立起一套通信系统。这套通信系统就是连接N个点的一个树。 这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够 联通的树上路过它的简单路径的数量。

例如,在上图中,现在一共有了5条边。其中,(3,8)这条边的负载是6,因 为有六条简单路径2-3-8,2-3-8-7,3-8,3-8-7,4-3-8,4-3-8-7路过了(3,8)。 现在,你的任务就是随着边的添加,动态的回答小强对于某些边的负载的 询问。

输入格式

第一行包含两个整数N,Q,表示星球的数量和操作的数量。星球从1开始编号。

接下来的Q行,每行是如下两种格式之一:

A x y 表示在x和y之间连一条边。保证之前x和y是不联通的。

Q x y 表示询问(x,y)这条边上的负载。保证x和y之间有一条边。 1≤N,Q≤100000

输出格式

对每个查询操作,输出被查询的边的负载。

样例一

input

8 6
A 2 3
A 3 4
A 3 8
A 8 7
A 6 5
Q 3 8

output

  6


解题思路:

维护子树信息,建虚树嘛。

pushup时将虚子树答案合并即可。

然后在换儿子/父亲时更新虚子树信息。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll tr[spc].ch[0]
  5 #define rrr tr[spc].ch[1]
  6 #define ls ch[0]
  7 #define rs ch[1]
  8 const int N=200000;
  9 struct trnt{
 10     int ch[2];
 11     int fa;
 12     int lzt;
 13     int wgt;
 14     int wgti;
 15     bool anc;
 16 }tr[N];
 17 int n,q;
 18 char cmd[10];
 19 bool whc(int spc)
 20 {
 21     return tr[tr[spc].fa].rs==spc;
 22 }
 23 void pushup(int spc)
 24 {
 25     tr[spc].wgt=tr[spc].wgti+1+tr[lll].wgt+tr[rrr].wgt;
 26     return ;
 27 }
 28 void trr(int spc)
 29 {
 30     if(!spc)
 31         return ;
 32     tr[spc].lzt^=1;
 33     std::swap(lll,rrr);
 34     return ;
 35 }
 36 void pushdown(int spc)
 37 {
 38     if(tr[spc].lzt)
 39     {
 40         trr(lll);
 41         trr(rrr);
 42         tr[spc].lzt=0;
 43     }
 44     return ;
 45 }
 46 void recal(int spc)
 47 {
 48     if(!tr[spc].anc)
 49         recal(tr[spc].fa);
 50     pushdown(spc);
 51     return ;
 52 }
 53 void rotate(int spc)
 54 {
 55     int f=tr[spc].fa;
 56     bool k=whc(spc);
 57     tr[f].ch[k]=tr[spc].ch[!k];
 58     tr[spc].ch[!k]=f;
 59     if(tr[f].anc)
 60     {
 61         tr[f].anc=0;
 62         tr[spc].anc=1;
 63     }else
 64         tr[tr[f].fa].ch[whc(f)]=spc;
 65     tr[spc].fa=tr[f].fa;
 66     tr[f].fa=spc;
 67     tr[tr[f].ch[k]].fa=f;
 68     pushup(f);
 69     pushup(spc);
 70     return ;
 71 }
 72 void splay(int spc)
 73 {
 74     recal(spc);
 75     while(!tr[spc].anc)
 76     {
 77         int f=tr[spc].fa;
 78         if(tr[f].anc)
 79         {
 80             rotate(spc);
 81             return ;
 82         }
 83         if(whc(spc)^whc(f))
 84             rotate(spc);
 85         else
 86             rotate(f);
 87         rotate(spc);
 88     }
 89     return ;
 90 }
 91 void access(int spc)
 92 {
 93     int lst=0;
 94     while(spc)
 95     {
 96         splay(spc);
 97         tr[spc].wgti-=tr[lst].wgt;
 98         tr[spc].wgti+=tr[rrr].wgt;
 99         tr[rrr].anc=true;
100         tr[lst].anc=false;
101         rrr=lst;
102         pushup(spc);
103         lst=spc;
104         spc=tr[spc].fa;
105     }
106     return ;
107 }
108 void Mtr(int spc)
109 {
110     access(spc);
111     splay(spc);
112     trr(spc);
113     return ;
114 }
115 void split(int x,int y)
116 {
117     Mtr(x);
118     access(y);
119     splay(y);
120     return ;
121 }
122 void link(int x,int y)
123 {
124     split(x,y);
125     tr[x].fa=y;
126     tr[y].wgti+=tr[x].wgt;
127     pushup(y);
128     return ;
129 }
130 int main()
131 {
132     scanf("%d%d",&n,&q);
133     for(int i=1;i<=n;i++)
134         tr[i].anc=true;
135     while(q--)
136     {
137         scanf("%s",cmd);
138         if(cmd[0]=='A')
139         {
140             int x,y;
141             scanf("%d%d",&x,&y);
142             link(x,y);
143         }else{
144             int x,y;
145             scanf("%d%d",&x,&y);
146             split(x,y);
147             long long ans=(long long)((long long)(tr[x].wgti+1)*(long long)(tr[y].wgti+1));
148             printf("%lld\n",ans);
149         }
150     }
151     return 0;
152 }

 

posted @ 2018-09-13 13:18  Unstoppable728  阅读(141)  评论(0编辑  收藏  举报