题解【大融合】
剛剛學了學LCT維護子樹信息,FlshHu大佬太強了%%%
題目描述
小強要在NN個孤立的星球上建立起一套通信系統。這套通信系統就是連接NN個點的一個樹。 這個樹的邊是一條一條添加上去的。在某個時刻,一條邊的負載就是它所在的當前能夠 聯通的樹上路過它的簡單路徑的數量。
例如,在上圖中,現在一共有了55條邊。其中,(3,8)(3,8)這條邊的負載是66,因 為有六條簡單路徑2-3-82?3?8,2-3-8-72?3?8?7,3-8,3-8-73?8,3?8?7,4-3-84?3?8,4-3-8-74?3?8?7路過了(3,8)(3,8)。
現在,你的任務就是隨著邊的添加,動態的回答小強對于某些邊的負載的 詢問。
輸入輸出格式
輸入格式:
?
第一行包含兩個整數?N, QN,Q,表示星球的數量和操作的數量。星球從?11?開始編號。
接下來的?QQ?行,每行是如下兩種格式之一:
- A x y?表示在?xx和?yy?之間連一條邊。保證之前?xx?和?yy是不聯通的。
- Q x y表示詢問?(x,y)(x,y)?這條邊上的負載。保證?xx?和?yy?之間有一條邊。
?
輸出格式:
?
對每個查詢操作,輸出被查詢的邊的負載。
解:
首先,來思考一下對于維護虛子樹信息如何pushup.
實子樹很簡單,虛加實咯。
對于每一次access和link操作,應該更新修改一下當前的虛子樹信息。因為這時它的父子關系發生的改變。
比如本題的pushup,就應該是左右實子樹信息加上自己的虛子樹信息+1.
也可以用來求子樹和,改成sum即可。
推薦FlashHudalao的博客。
代碼:
#include<cstdio> #include<iostream> using namespace std; struct node{int s,si,fa,ch[2],val,rev; }tr[500000]; char ch[4]; inline void pushup(int x){tr[x].s=tr[tr[x].ch[0]].s+tr[tr[x].ch[1]].s+tr[x].si+1; }inline void pushr(int x){if(!x)return;swap(tr[x].ch[0],tr[x].ch[1]);tr[x].rev^=1; }inline void pushdown(int x){if(tr[x].rev){pushr(tr[x].ch[0]);pushr(tr[x].ch[1]);tr[x].rev=0;} }inline bool root(int x){int g=tr[x].fa;return !(tr[g].ch[0]==x||tr[g].ch[1]==x); }inline void update(int x){if(!root(x))update(tr[x].fa);pushdown(x); }inline void rotate(int x){int y=tr[x].fa,z=tr[y].fa,k=tr[y].ch[1]==x;if(!root(y))tr[z].ch[tr[z].ch[1]==y]=x;tr[x].fa=z;tr[y].ch[k]=tr[x].ch[k^1];if(tr[x].ch[k^1])tr[tr[x].ch[k^1]].fa=y;tr[x].ch[k^1]=y;tr[y].fa=x;pushup(y);pushup(x); }inline void splay(int x){int y,z;update(x);while(!root(x)){y=tr[x].fa,z=tr[y].fa;if(!root(y))(tr[y].ch[1]==x)^(tr[z].ch[1]==y)?rotate(x):rotate(y);rotate(x);}pushup(x); }inline void access(int x){for(int y=0;x;y=x,x=tr[x].fa){splay(x);tr[x].si+=tr[tr[x].ch[1]].s;tr[x].ch[1]=y;tr[x].si-=tr[tr[x].ch[1]].s;pushup(x);} }inline void makeroot(int x){access(x);splay(x);pushr(x); }inline void split(int x,int y){makeroot(x);access(y);splay(y); }inline void link(int x,int y){split(x,y);tr[x].fa=y;tr[tr[x].fa].si+=tr[x].s;pushup(y); }int n,q,a,b; int main(){scanf("%d%d",&n,&q);for(int i=1;i<=n;++i)tr[i].s=1;for(int i=1;i<=q;++i){cin>>ch;if(ch[0]=='A'){scanf("%d%d",&a,&b);link(a,b);}else{scanf("%d%d",&a,&b);split(a,b);printf("%lld\n",(long long)(tr[a].si+1)*(tr[b].si+1));}}return 0; }?
轉載于:https://www.cnblogs.com/h-lka/p/10989471.html
總結
- 上一篇: R语言实现多线性回归模型预测时间序列数据
- 下一篇: 001-supervisor