洛谷3345 幻想鄉戰略遊戲(動態樹分治)

2021-08-09 12:05:35 字數 2295 閱讀 3964

現在終於下午停課了,就是說我只要熬過早上就可以盡情怠惰專心學習了。 題面

由於我還沒入東方,所以就由我來粗鄙地口胡題意吧:

一棵n個點的樹,邊有長度,點有點權d。每次更改乙個點的點權,然後讓你找乙個點x,最小化∑i

=1nd

is(i

,x)∗

d[i]

輸出這個最小值。

經過一輪膜大佬的題解,我發現了原來有乙個叫帶權重心的東西。本題的點x就是帶權重心。

定義為刪掉該點後,得到的連通塊權值和最大的最小的點。

性質為所有點到它的帶權距離和最小。

設siz[x]為子樹x的權值和。

對於原樹的點x和x的兒子son。若siz[son]*2>total。則帶權重心在子樹son中。若沒有這樣的兒子,則x即為帶權重心。由此思想,我們可以由根開始一路往下找,直到沒有這樣兒子的點為止。

這樣貌似就可以ac。這個演算法隨著樹的深度增大就變得灰常慢。所以我們需要減小樹的深度,據此就想到點分樹。

我們先構出原樹的不帶權點分樹,siz[x]以為x為重心的連通塊的權值和。對於點x和x在點分樹上的兒子son,若siz[son]*2>total。則帶權重心在連通塊son中。

x指向連通塊son的邊指向u,把點分樹上u到son路徑上的點的siz全部加上(siz[x]-siz[son])。再去連通塊son中找,找到後再把加上的減回去。

考慮如何統計答案。我們還要再維護幾個資訊,設p[x]為x在點分樹上的父親,記h[x]為僅考慮x的連通塊,選p[x]時的答案。g[x]為x在點分樹上所有兒子的h之和。

設帶權重心為x,由x一直往點分樹的父親上走,設當前走到y

g[p[y]]-h[y]+dis(p[y],x)*(siz[p[y]]-siz[x]) 可以貢獻答案。

據說要用一種o(1)求lca的才不超時,具體是這樣的:

在樹的尤拉序中,x和y第一次出現的位置之間的序列中深度最小的點就是x和y的lca。可用rmq維護。

複雜度nlo

g2n 。

#include 

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

#define mmst(a, b) memset(a, b, sizeof(a))

#define mmcp(a, b) memcpy(a, b, sizeof(b))

typedef long long ll;

const int n=200200,oo=1e9;

void read(int &hy)

}int to[n],nex[n],head[n],son[n],cnt;

int n,m,bigroot;

bool vis[n];

int w[n],tim[n],times;

int ff[n],p[n],siz[n],gg[n],sum,root;

int b[2

*n],er[20],rmq[2*n][19];

ll val[n],dep[n],f[n],g[n],h[n],sumd;

ll ans;

void add(int u,int v,ll va)

void ljdfs(int

x,int fa)

}void pre()

ll dis(int

x,int

y)void dfs(int

x,int fa)

gg[x]=max(gg[x],sum-siz[x]);

if(gg[x]x;

}void dfs2(intx)}

void update(int

x,ll ad)

}}void find(int

x) root=x;

}int main()

pre();

gg[0]=oo;

sum=n;

dfs(1,1);

bigroot=root;

dfs2(root);

while(m--)

return

0;}

如果你們看新番《如果有…》,看到有彈幕說「嫉妒使我旋轉卡殼,嫉妒使我狀態壓縮…」。那也許就是本蒟蒻發的。

洛谷P3345 ZJOI2015 幻想鄉戰略遊戲

題目描述 傲嬌少女幽香正在玩乙個非常有趣的戰略類遊戲,本來這個遊戲的地圖其實還不算太大,幽香還能管得過來,但是不知道為什麼現在的網遊廠商把遊戲的地圖越做越大,以至於幽香一眼根本看不過來,更別說和別人打仗了。在打仗之前,幽香現在面臨乙個非常基本的管理問題需要解決。整個地圖是乙個樹結構,一共有n塊空地,...

洛谷P3345 ZJOI2015 幻想鄉戰略遊戲

傳送門 先考慮乙個簡單的問題 怎麼在有修改的情況下快速求乙個點作為補給站的答案。注意到和路徑有關,所以很容易想到點分樹。接著可以想到乙個十分暴力的做法,就是修改後,每次列舉相鄰的點,如果更優就走過去。很容易想到因為每次重心不會移動太遠,這個是可以過的,資料也不太好造來卡這個做法。那麼有沒有穩定的做法...

P3345 ZJOI2015 幻想鄉戰略遊戲

題意 求帶權重心,即求乙個點 u 使得最小化 sum dis u,v times w v 輸出這個最小值。點權帶修,多組詢問。動態點分治。先建出點分樹,以下的父子關係均是建立在點分樹上的。s u 表示子樹 u 的點權和 sfa u 表示子樹 u 對 fa u 的貢獻,即 sum dis v,fa u...