日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

P4332-[SHOI2014]三叉神经树【LCT】

發布時間:2023/12/3 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 P4332-[SHOI2014]三叉神经树【LCT】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

正題

題目鏈接:https://www.luogu.com.cn/problem/P4332


題目大意

給出nnn個點的一棵有根三叉樹,保證每個點的兒子個數為333或者000,每個葉子有一個權值000111,每個非葉子節點的權值是它兒子中權值較多的那個,每次修改一個葉子的權值,求根節點的權值。

1≤n,q≤5×1051\leq n,q\leq 5\times 10^51n,q5×105


解題思路

修改一個節點會影響的權值顯然是它到根節點路徑上的一個前綴。

然后考慮什么樣的節點會受到影響,如果000改為111那么一路上原來恰好為兩個000的節點就會被修改,那么我們的思路是考慮找到這條路徑上第一個111的個數不為111的節點。

而且考慮上修改的話十分的麻煩,因為O(nlog?2n)O(n\log^2 n)O(nlog2n)過不去所以不考慮樹剖,可以考慮一下LCTLCTLCT。

我們可以先聯通修改點到根的節點,然后在SplaySplaySplay上二分出第一個不為111的節點,然后對于它和它的右子樹暴力修改即可。

111改為000同理,維護第一個不為222的節點即可。

時間復雜度O(nlog?n)O(n\log n)O(nlogn)


code

#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<stack> using namespace std; const int N=2e6+10; int n,m,ans,fa[N],v[N],w1[N],w2[N],lazy[N],t[N][2]; vector<int> G[N];stack<int> s; bool Nroot(int x) {return fa[x]&&(t[fa[x]][0]==x||t[fa[x]][1]==x);} bool Direct(int x) {return t[fa[x]][1]==x;} void PushUp(int x){if(w1[t[x][1]])w1[x]=w1[t[x][1]];else if(v[x]!=1)w1[x]=x;else w1[x]=w1[t[x][0]];if(w2[t[x][1]])w2[x]=w2[t[x][1]];else if(v[x]!=2)w2[x]=x;else w2[x]=w2[t[x][0]];return; } void PushR(int x,int w) {v[x]^=3;swap(w1[x],w2[x]);lazy[x]+=w;return;} void PushDown(int x){if(!lazy[x])return;PushR(t[x][0],lazy[x]);PushR(t[x][1],lazy[x]);lazy[x]=0;return; } void Rotate(int x){int y=fa[x],z=fa[y];int xs=Direct(x),ys=Direct(y);int w=t[x][xs^1];if(Nroot(y))t[z][ys]=x;t[x][xs^1]=y;t[y][xs]=w;if(w)fa[w]=y;fa[y]=x;fa[x]=z;PushUp(y);PushUp(x);return; } void Splay(int x){int y=x;s.push(x);while(Nroot(y))y=fa[y],s.push(y);while(!s.empty())PushDown(s.top()),s.pop();while(Nroot(x)){y=fa[x];if(!Nroot(y))Rotate(x);else if(Direct(x)==Direct(y))Rotate(y),Rotate(x);else Rotate(x),Rotate(x);}return; } void Access(int x){for(int y=0;x;y=x,x=fa[x])Splay(x),t[x][1]=y,PushUp(x);return; } void Updata(int x){int op=(v[x]^=2);x=fa[x];Access(x);Splay(x);if(op){if(w1[x]){x=w1[x];Splay(x);PushR(t[x][1],1);PushUp(t[x][1]);v[x]++;PushUp(x);}else ans=!ans,PushR(x,1),PushUp(x);}else{if(w2[x]){x=w2[x];Splay(x);PushR(t[x][1],-1);PushUp(t[x][1]);v[x]--;PushUp(x);}else ans=!ans,PushR(x,-1),PushUp(x);}return; } void dfs(int x){for(int i=0;i<G[x].size();i++){int y=G[x][i];dfs(y);v[x]+=(v[y]>>1);}PushUp(x);return; } int main() {scanf("%d",&n);for(int i=1;i<=n;i++){int x,y,z;scanf("%d%d%d",&x,&y,&z);fa[x]=fa[y]=fa[z]=i;G[i].push_back(x);G[i].push_back(y);G[i].push_back(z);}for(int i=n+1;i<=3*n+1;i++)scanf("%d",&v[i]),v[i]<<=1;dfs(1);ans=v[1]>>1;scanf("%d",&m);while(m--){int x;scanf("%d",&x);Updata(x);printf("%d\n",ans);}return 0; }

總結

以上是生活随笔為你收集整理的P4332-[SHOI2014]三叉神经树【LCT】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。