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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

洛谷P4219 大融合(LCT、虚子树)

發布時間:2023/12/3 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 洛谷P4219 大融合(LCT、虚子树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解析

本題需要用LCT維護子樹大小
然后我就不會了
然后我就用樹剖水過去了
又快又好寫,真香

現在詳細聊聊如何用LCT維護子樹信息
每個結點再定義一個新的變量記錄所有虛兒子的信息
然后…完了?

告別盲目pushup,我們來詳細聊聊在哪里需要更新虛兒子的信息

毋庸置疑,應該在虛兒子信息改變的時候(廢話)
那么什么時候發生改變呢?

  • access:虛實邊會交換狀態,需要更新虛子樹狀態
  • link:增加了虛兒子,需要更新虛子樹狀態
  • 沒了
    splay、rotate、makeroot、findroot都是在一個splay里自己玩泥巴,顯然不會改變虛兒子的狀態
    注意cut是減少了一個實兒子,也沒有改變虛兒子狀態
    似乎還不太難對吧
    所以,對于LCT的標記問題,我們要理性分析,相信科學

    update:

    紙上得來終覺淺,絕知此事要躬行

    (翻譯:不要口胡)
    qwq
    不自己寫一遍是真的找不到坑點…
    這里的link改變虛子樹狀態的時候,會連帶上面一串splay的信息都出問題!
    而且由于其他地方默認的是原來的信息正確,因此這里即使后面splay或makeroot也于事無補
    解決辦法是把y轉到根再更新其虛子樹信息

    inline void link(int x,int y){makeroot(x);access(y);splay(y);siz0[y]+=siz[x];f[x]=y;pushup(y);return; }

    代碼

    然而懶得重寫,還是貼的我的樹剖
    明天晨練可以寫遍這個

    #include<bits/stdc++.h> using namespace std; #define ll long long const int N=2e5+100; const int mod=1e9+7; const double eps=1e-9; inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f; }int n,m; struct node{int to,nxt; }p[N<<1]; int fi[N],cnt; inline void addline(int x,int y){p[++cnt]=(node){y,fi[x]};fi[x]=cnt;return; } struct ope{int op,x,y; }q[N]; struct edge{int x,y; }e[N]; int tot,fa[N],num[N]; int find(int x){return x==fa[x]?x:find(fa[x]);} inline void merge(int x,int y){x=find(x);y=find(y);if(num[x]>num[y]) swap(x,y);e[++tot]=(edge){x,y};fa[x]=y;num[y]+=num[x];return; }int dfn[N],pos[N],tim,f[N],siz[N],hson[N],top[N]; int pl[N][19]; void dfs1(int x,int fa){f[x]=fa;pl[x][0]=fa;for(int k=1;pl[x][k-1];k++) pl[x][k]=pl[pl[x][k-1]][k-1];siz[x]=1;for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==fa) continue;dfs1(to,x);siz[x]+=siz[to];if(siz[to]>siz[hson[x]]) hson[x]=to;}return; } void dfs2(int x,int tp){top[x]=tp;pos[x]=++tim;dfn[tim]=x;if(hson[x]) dfs2(hson[x],tp);for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f[x]||to==hson[x]) continue;dfs2(to,to);}return; }int val[N]; inline void add(int p,int w){for(;p<=n;p+=p&-p) val[p]+=w;return; } inline int ask(int p){int res(0);for(;p;p-=p&-p) res+=val[p];return res; } void init(){for(int i=1;i<=n;i++){add(pos[i],siz[i]);add(pos[i]+1,-siz[i]);}return; }void upd(int x,int anc,int w){while(top[x]!=top[anc]){add(pos[top[x]],w);add(pos[x]+1,-w);x=f[top[x]];}add(pos[anc],w);add(pos[x]+1,-w);return; }ll ans[N]; int o; int main() { #ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout); #endifmemset(fi,-1,sizeof(fi));cnt=-1;n=read();m=read();for(int i=1;i<=n;i++) num[i]=1,fa[i]=i;for(int i=1;i<=m;i++){char c;int x,y;scanf(" %c",&c);x=read(),y=read();q[i]=(ope){c=='A',x,y};if(c=='A'){addline(x,y);addline(y,x);merge(x,y);}}for(int i=1;i<=n;i++){if(!siz[i]){dfs1(i,0);dfs2(i,i);}}init();for(int i=m;i>=1;i--){if(q[i].op){int x=e[tot].x,y=e[tot].y;--tot;num[y]-=num[x];fa[x]=x;x=q[i].x,y=q[i].y; if(f[x]==y) swap(x,y);int w=ask(pos[y]);int tp=x,oo=find(x);for(int k=17;k>=0;k--){if(!pl[tp][k]||find(pl[tp][k])!=oo) continue;tp=pl[tp][k];}upd(x,tp,-w);//printf("cut:(%d %d) w=%d tp=%d\n\n",x,y,w,tp);}else{int x=q[i].x,y=q[i].y;if(f[x]==y) swap(x,y);int sum=num[find(x)],bot=ask(pos[y]);ans[++o]=1ll*bot*(sum-bot);//printf("(%d %d):sum=%d bot=%d\n\n",x,y,sum,bot);}}while(o) printf("%lld\n",ans[o--]);return 0; } /* 8 12 A 2 3 Q 2 3 A 3 4 Q 2 3 A 3 8 Q 3 8 Q 3 4 Q 2 3 A 8 7 A 6 5 Q 8 7 Q 5 6*/

    總結

    以上是生活随笔為你收集整理的洛谷P4219 大融合(LCT、虚子树)的全部內容,希望文章能夠幫你解決所遇到的問題。

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