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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【SPOJ2666】QTree4【链分治】

發布時間:2023/12/3 c/c++ 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SPOJ2666】QTree4【链分治】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

傳送門

題意:給一棵帶邊權的樹,每個點開始時為白色,維護兩種操作:

1.改變一個點的顏色(白變黑,黑變白)
2.詢問最遠的兩個白點之間的距離

樹分治國集論文

鏈分治的本質其實就是樹鏈剖分。它們的區別是樹剖維護路徑詢問,鏈分治維護全局路徑。

動態點分治需要重新建一棵樹,而鏈分治分出來的是鏈,本身就可以用數據結構維護。所以鏈分治本身就可以資瓷修改。

對于每一條鏈單獨用數據結構維護與當前鏈有交集的路徑信息。

對于本題,先樹鏈剖分

Di,Di′D_i,D_i'Di?,Di?為節點iii沿虛邊往下走到某個白點的最長和次長長度。如果不存在,記為?INF-INF?INF

用線段樹維護一條鏈。對于一條鏈上的一個區間[L,R][L,R][L,R]

lmax=max{dist(L,i)+Di}lmax=max\{dist(L,i)+D_i\}lmax=max{dist(L,i)+Di?}

rmax=max{Di+dist(i,R)}rmax=max\{D_i+dist(i,R)\}rmax=max{Di?+dist(i,R)}

即:lmaxlmaxlmax表示LLL沿這條鏈往下走(可以不走),在[L,R][L,R][L,R]中的某個點拐出去,往下走(可以不走)到某個白點經過的最長長度。注意沒有要求起點是白色rmaxrmaxrmax同理。

再記錄ansansans表示有交集的最長長度

然后用類似最大子段和的方式合并。

對于一個線段樹節點ppp,左右兒子lc,rclc,rclc,rc

lmax[p]=max{lmax[lc],dist(L,mid+1)+lmax[rc]}lmax[p]=max\{lmax[lc],dist(L,mid+1)+lmax[rc]\}lmax[p]=max{lmax[lc],dist(L,mid+1)+lmax[rc]}

rmax[p]=max{rmax[lc]+dist(mid,R),rmax[rc]}rmax[p]=max\{rmax[lc]+dist(mid,R),rmax[rc]\}rmax[p]=max{rmax[lc]+dist(mid,R),rmax[rc]}

ans[p]=max{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]}ans[p]=max\{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]\}ans[p]=max{ans[lc],ans[rc],rmax[lc]+dist(mid,mid+1)+lmax[rc]}

邊界:當L=RL=RL=R,設當前點為iii

iii是白點

lmax=rmax=max{Di,0}lmax=rmax=max\{D_i,0\}lmax=rmax=max{Di?,0}

ans=max{0,Di,Di+Di′}ans=max\{0,D_i,D_i+D_i'\}ans=max{0,Di?,Di?+Di?}

否則

lmax=rmax=Dilmax=rmax=D_ilmax=rmax=Di?

ans=Di+Di′ans=D_i+D_i'ans=Di?+Di?

最后需要維護Di,Di′D_i,D_i'Di?,Di?

iii是白點,jjjiii的輕兒子

Di=max{0,w(i,j)+lmax[j]}D_i=max\{0,w(i,j)+lmax[j]\}Di?=max{0,w(i,j)+lmax[j]}

iii是黑點

Di=w(i,j)+lmax[j]D_i=w(i,j)+lmax[j]Di?=w(i,j)+lmax[j]

然后用個堆之類的瞎維護即可

然而寫起來十分精神污染

有一個常用的轉換方式

紅色邊權值為000

這樣這棵樹變成了二叉樹,且兩兩之間的距離不變。也就是說和原來的樹是等效的。

有什么用呢?

這樣一個節點最多有一個重兒子一個輕兒子,Di′D_i'Di?永遠為?INF-INF?INFDiD_iDi?可以直接計算,大大降低編程復雜度。當然好不好調是另外一回事

最后答案用multisetmultisetmultiset暴艸即可

復雜度O(nlogn2)O(nlog_n^2)O(nlogn2?)

#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <set> #define MAXN 200005 #define INF 0x3f3f3f3f using namespace std; inline int read() {int ans=0,f=1;char c=getchar();while (c<'0'||c>'9'){if (c=='-') f=-1;c=getchar();}while (c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}return f*ans; } inline char gal() {char c=getchar();while (c<'A'||c>'Z') c=getchar();return c; } int n; struct edge {int u,v,w; }e[MAXN]; int head[MAXN],nxt[MAXN],cnt; void addnode(int u,int v,int w) {e[++cnt]=(edge){u,v,w};nxt[cnt]=head[u];head[u]=cnt; } int son[MAXN][2]; int fa[MAXN],dep[MAXN],cost[MAXN],col[MAXN]; void dfs(int u) {int las=u;for (int i=head[u];i;i=nxt[i])if (!dep[e[i].v]){fa[fa[e[i].v]=++n]=las;dep[e[i].v]=dep[u]+1;cost[e[i].v]=e[i].w;dfs(son[las=son[las][las!=u]=n][0]=e[i].v);} } int siz[MAXN],dis[MAXN],tp[MAXN],bt[MAXN]; int dfn[MAXN],pos[MAXN],tim; void Dfs(int u) {if (!u) return;siz[u]=1;Dfs(son[u][0]),Dfs(son[u][1]);siz[u]+=siz[son[u][0]]+siz[son[u][1]];if (siz[son[u][0]]<siz[son[u][1]]) swap(son[u][0],son[u][1]); } multiset<int> re; int rt[MAXN],tot; int ch[MAXN<<2][2],lmax[MAXN<<2],rmax[MAXN<<2],ans[MAXN<<2]; inline int d(const int& x) {if (!son[x][1]) return col[x]? 0:-INF;if (col[x]) return max(cost[son[x][1]]+lmax[rt[son[x][1]]],0);return cost[son[x][1]]+lmax[rt[son[x][1]]]; } #define lc ch[p][0] #define rc ch[p][1] inline void update(const int& p,const int& l,const int& r) {int mid=(l+r)>>1;lmax[p]=max(lmax[lc],dis[pos[mid+1]]-dis[pos[l]]+lmax[rc]);rmax[p]=max(rmax[lc]+dis[pos[r]]-dis[pos[mid]],rmax[rc]);ans[p]=max(max(ans[lc],ans[rc]),rmax[lc]+cost[pos[mid+1]]+lmax[rc]); } void build(int& p,int l,int r) {p=++tot;if (l==r){if (col[pos[l]]) ans[p]=lmax[p]=rmax[p]=max(0,d(pos[l]));else lmax[p]=rmax[p]=d(pos[l]),ans[p]=-INF;return;}int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);update(p,l,r); } void modify(int p,int l,int r,int k) {if (l==r){if (col[pos[l]]) ans[p]=lmax[p]=rmax[p]=max(0,d(pos[l]));else lmax[p]=rmax[p]=d(pos[l]),ans[p]=-INF;return;}int mid=(l+r)>>1;if (k<=mid) modify(lc,l,mid,k);else modify(rc,mid+1,r,k);update(p,l,r); } void DFS(int u,int t) {if (!u) return;dis[u]=dis[fa[u]]+cost[u];bt[tp[u]=t]=pos[dfn[u]=++tim]=u;DFS(son[u][0],t);DFS(son[u][1],son[u][1]);if (u==t) build(rt[u],dfn[u],dfn[bt[u]]),re.insert(ans[rt[u]]); } int main() {freopen("test.in","r",stdin);n=read();int cnt=n;for (int i=1;i<=n;i++) col[i]=1;for (int i=1;i<n;i++){int u,v,w;u=read(),v=read(),w=read();addnode(u,v,w),addnode(v,u,w);}dep[1]=1;dfs(1);Dfs(1);DFS(1,1);for (int i=read();i;--i){if (gal()=='A') cnt? printf("%d\n",max(0,*re.rbegin())):puts("They have disappeared.");else{int x=read();for ((col[x]^=1)? ++cnt:--cnt;x;re.erase(re.find(ans[rt[tp[x]]])),modify(rt[tp[x]],dfn[tp[x]],dfn[bt[tp[x]]],dfn[x]),re.insert(ans[rt[tp[x]]]),x=fa[tp[x]]);}}return 0; }

做這種題一定要先理清思路,弄懂定義再開始碼,不要邊想邊寫

總結

以上是生活随笔為你收集整理的【SPOJ2666】QTree4【链分治】的全部內容,希望文章能夠幫你解決所遇到的問題。

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