传送门

题意:写一个数据结构,支持图上连边(保证图是森林)和询问一条边两端的连通块大小的乘积。$\text{点数、询问数} \leq 10^5$


图上连边,$LCT$跑不掉

支持子树$size$有点麻烦。我们需要虚子树的$size$和(实子树的可以直接$pushup$),那么我们对于每一个点就去维护其虚子树的$size$和,那么每一个点的子树和就是可以维护的了。可以知道只有$link$和$access$操作会修改虚子树和(其他都在实链上进行操作),稍微加一点东西就行了。相对来说还是比较裸。

注意$pushup$的改变。

 #include<bits/stdc++.h>
 //This code is written by Itst
 using namespace std;

 inline int read(){
     ;
     ;
     char c = getchar();
     while(c != EOF && !isdigit(c)){
         if(c == '-')
             f = ;
         c = getchar();
     }
     while(c != EOF && isdigit(c)){
         a = (a << ) + (a << ) + (c ^ ');
         c = getchar();
     }
     return f ? -a : a;
 }

 ;
 struct node{
     ] , fa , allSize;
     bool mark;
 }Tree[MAXN];
 int N , M;

 inline bool nroot(int x){
     ] == x || Tree[Tree[x].fa].ch[] == x;
 }

 inline bool son(int x){
     ] == x;
 }

 inline void pushup(int x){
     Tree[x].allSize = Tree[Tree[x].ch[]].allSize + Tree[Tree[x].ch[]].allSize + Tree[x].size + ;
 }

 inline void ZigZag(int x){
     bool f = son(x);
     ];
     if(nroot(y))
         Tree[z].ch[son(y)] = x;
     Tree[x].fa = z;
     Tree[x].ch[f ^ ] = y;
     Tree[y].fa = x;
     Tree[y].ch[f] = w;
     if(w)
         Tree[w].fa = y;
     pushup(y);
     pushup(x);
 }

 inline void pushdown(int x){
     if(Tree[x].mark){
         Tree[Tree[x].ch[]].mark ^= ;
         Tree[Tree[x].ch[]].mark ^= ;
         Tree[x].mark = ;
         swap(Tree[x].ch[] , Tree[x].ch[]);
     }
 }

 void pushdown_all(int x){
     if(nroot(x))
         pushdown_all(Tree[x].fa);
     pushdown(x);
 }

 inline void Splay(int x){
     pushdown_all(x);
     while(nroot(x)){
         if(nroot(Tree[x].fa))
             ZigZag(son(x) == son(Tree[x].fa) ? Tree[x].fa : x);
         ZigZag(x);
     }
 }

 inline void access(int x){
      ; x ; y = x , x = Tree[x].fa){
         Splay(x);
         Tree[x].size = Tree[x].size + Tree[Tree[x].ch[]].allSize - Tree[y].allSize;
         Tree[x].ch[] = y;
         pushup(x);
     }
 }

 inline void makeroot(int x){
     access(x);
     Splay(x);
     Tree[x].mark ^= ;
 }

 inline void split(int x , int y){
     makeroot(x);
     access(y);
     Splay(y);
 }

 inline void link(int x , int y){
     split(x , y);
     Tree[x].fa = y;
     Tree[y].size += Tree[x].allSize;
     pushup(y);
 }

 inline char getc(){
     char c = getchar();
     while(!isupper(c))
         c = getchar();
     return c;
 }

 int main(){
 #ifndef ONLINE_JUDGE
     freopen("4219.in" , "r" , stdin);
     //freopen("4219.out" , "w" , stdout);
 #endif
     N = read();
      ; i <= N ; ++i)
         Tree[i].allSize = ;
     for(M = read() ; M ; --M)
         if(getc() == 'A')
             link(read() , read());
         else{
             int a = read() , b = read();
             split(a , b);
             printf("%lld\n" , 1ll * Tree[a].allSize * (Tree[b].allSize - Tree[a].allSize));
         }
     ;
 }
05-11 15:34
查看更多