LOJ 6463 AK YOI 樹分治 線段樹合併

2022-02-27 13:04:40 字數 2321 閱讀 7688

傳送門

既然是樹上路徑統計問題,不難想到要使用樹分治,這裡以點分治為例

由點分治的性質,每層只需要考慮經過重心的路徑

因為需要維護路徑長度在一定範圍內的最大權值和,所以要用乙個資料結構維護一下到根節點距離在一定範圍內的最大權值和

顯然線段樹是乙個不錯的選擇,對每個子樹建立乙個線段樹,根節點的答案用每個子樹的線段樹都更新一遍即可

考慮更新子樹中的點的答案,這時需要使用除這棵子樹外的所有子樹的線段樹一起更新

我們可以使用線段樹合併來維護,給子樹任意確定乙個順序,然後通過維護每個子樹的字首和字尾線段樹的並即可快速得到除去某棵子樹後的線段樹

顯然複雜度是***的,因為線段樹合併的複雜度無論如何都不會高於暴力插入三遍

總複雜度\(o(n\log^2 n)\),常數應該不小,不過跑的挺快233333

#includeusing namespace std;

const int maxn=100005,maxm=maxn*100;

const long long inf=0x5f5f5f5f5f5f5f5fll;

void solve(int,int);

int getcenter(int,int);

int getdis(int);

void getans(int,int);

void modify(int,int,int&);

int merge(int,int);

long long query(int,int,int);

long long mx[maxm];

int lc[maxm],rc[maxm],cnt=0,root[maxn],prefix[maxn],suffix[maxn];

vectorg[maxn];

bool vis[maxn];

long long w[maxn],ans[maxn],ant[maxn],tmp;

int p[maxn],size[maxn],son[maxn],q[maxn],d[maxn],pr[maxn],nx[maxn];

int n,m,l,r,val[maxn],s,t;

int main()

for(int i=1,x,y;i1)printf(" ");

printf("%lld",ans[i]);

} printf("\n");

return 0;

}void solve(int x,int sz)

s=l;t=r;

for(int i=0,last=0;i<(int)g[x].size();i++)

if(!vis[g[x][i]])

ant[x]=-inf;

for(int i=(int)g[x].size()-1,last=0;~i;i--)

if(!vis[g[x][i]])

for(int i=0;i<(int)g[x].size();i++)

if(!vis[g[x][i]])getans(g[x][i],val[x]);

ans[x]=max(ans[x],ant[x]);

root[x]=0;

for(int i=0;i<(int)g[x].size();i++)

if(!vis[g[x][i]])

cnt=0;

for(int i=0;i<(int)g[x].size();i++)

if(!vis[g[x][i]])solve(g[x][i],size[g[x][i]]);

}int getcenter(int x,int s)

} for(int i=tail-1;i;i--)

x=q[0];

while(son[x]&&size[son[x]]>(s>>1))x=son[x];

return x;

}int getdis(int x)

} for(int i=tail-1;i;i--)

return d[q[tail-1]];

}void getans(int x,int v)

} for(int i=tail-1;~i;i--)

}void modify(int l,int r,int &rt)

mx[rt]=max(mx[rt],tmp);

if(l==r)return;

int mid=(l+r)>>1;

if(s<=mid)modify(l,mid,lc[rt]);

else modify(mid+1,r,rc[rt]);

}int merge(int x,int y)

long long query(int l,int r,int rt)

線段樹分治

動態圖聯通性 可離線 loj121 給你一張無向圖,你要支援如下操作 1 刪除一條邊 2 加入一條邊 3 查詢某兩個點對間是否聯通 離線做法 線段樹分治 口胡做法 把操作的順序當做時間。每條邊維護乙個存活區間,代表這條邊在這個時間區間裡面活著。對時間軸建立一顆線段樹,從線段樹根開始dfs。進入乙個子...

線段樹分治

首先,這裡的線段樹是狹義的線段樹。而線段樹分治是一種維護時間區間的資料結構,利用線段樹的分治性使時間複雜度為log loglo g級別。維護時間區間的資料結構有cdq分治 kd tree,那麼線段樹分治和它們的區別在 呢?其實,它就是用回退操作來實現可持久化,或者說是維護了操作會影響的時間區間。我們...

線段樹分治

day2模擬被完爆了w 來學一波線段樹分治 原來一直拿它口胡其實沒寫過。然鵝這個東西和線段樹的關係 就像點分治和點分樹一樣 並不用建出來 但遍歷順序是一致的 從上到下 從左兒子到右兒子 訪問 線段樹 的所有節點 每個節點表示乙個區間 當然維護的也是區間裡的值 這就要求我們維護的東西滿足區間加法 比如...