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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

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

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

正題

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


題目大意

給出nnn個(gè)點(diǎn)的一棵有根三叉樹,保證每個(gè)點(diǎn)的兒子個(gè)數(shù)為333或者000,每個(gè)葉子有一個(gè)權(quán)值000111,每個(gè)非葉子節(jié)點(diǎn)的權(quán)值是它兒子中權(quán)值較多的那個(gè),每次修改一個(gè)葉子的權(quán)值,求根節(jié)點(diǎn)的權(quán)值。

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


解題思路

修改一個(gè)節(jié)點(diǎn)會影響的權(quán)值顯然是它到根節(jié)點(diǎn)路徑上的一個(gè)前綴。

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

而且考慮上修改的話十分的麻煩,因?yàn)?span id="ozvdkddzhkzd" class="katex--inline">O(nlog?2n)O(n\log^2 n)O(nlog2n)過不去所以不考慮樹剖,可以考慮一下LCTLCTLCT

我們可以先聯(lián)通修改點(diǎn)到根的節(jié)點(diǎn),然后在SplaySplaySplay上二分出第一個(gè)不為111的節(jié)點(diǎn),然后對于它和它的右子樹暴力修改即可。

111改為000同理,維護(hù)第一個(gè)不為222的節(jié)點(diǎn)即可。

時(shí)間復(fù)雜度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; }

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。