主席樹 BZOJ 4771 七彩樹

2021-07-28 08:30:24 字數 1734 閱讀 9729

感謝帶我飛的rxd大爺

我們先考慮不管深度限制可修改我們怎麼做

就是把每種顏色按照dfs序排列 然後給這些點都+1 但是相鄰兩個的lca處要-1 這樣子樹不同顏色數就是子樹和

然後我們把深度限制 看做按照深度的順序加點

加點我們需要維護什麼 每種顏色的序列 這個用set或平衡樹 在序列中插入 我們對前驅後繼lca什麼瞎處理一通 然後記一下這個版本 也就是在主席樹上修改

然後乙個深度限制 就相當於到那個深度版本的線段樹中詢問子樹和

#include

#include

#include

#include

using

namespace

std;

inline

char nc()

inline

void read(int &x)

const

int n=500005;

const

int k=25;

int root[n];

int ls[k*n],rs[k*n],sum[k*n];

int ncnt;

inline

void modify(int &y,int x,int l,int r,int t,int a)

if (t<=mid)

rs[y]=rs[x],modify(ls[y],ls[x],l,mid,t,a),sum[y]=sum[ls[y]]+sum[rs[y]];

else

ls[y]=ls[x],modify(rs[y],rs[x],mid+1,r,t,a),sum[y]=sum[ls[y]]+sum[rs[y]];

}inline

int query(int x,int l,int r,int ql,int qr)

struct edgeg[n<<1];

int head[n],inum;

inline

void add(int u,int v,int p)

#define v g[p].v

int clk;

int fat[n][k],depth[n];

int pre[n],size[n],back[n];

inline

void dfs(int u,int fa)

inline

int lca(int u,int v)

int n,m,maxd;

int clr[n];

set set[n];

typedef

set::iterator iter;

int idx[n];

inline

bool cmp(int a,int b)

if (l)

if (r)

modify(tmp,cur,1,n,pre[x],1); cur=tmp;

if (i==n || depth[idx[i+1]]!=depth[idx[i]])

root[depth[idx[i]]]=cur;

}int lastans=0,x,d;

while (m--)

for (int i=1;i<=n;i++) head[i]=0; inum=0;

for (int i=1;i<=n;i++) set[i].clear();

ncnt=0;

} return

0;}

BZOJ4771 七彩樹(主席樹)

點此看題面 考慮乙個子樹內所有點 dfs 序是連續的,所以我們可以將其轉化為序列然後用線段樹維護。又由於有深度限制,所以可以對不同深度建不同版本,使用主席樹。但是,本質不同顏色應該如何維護?考慮對於每一種顏色,如果有兩個該顏色的點同時出現,則相當於將這兩個點的權值分別加 1 而把它們 lca 的權值...

BZOJ 4771 主席樹 倍增 set

思路 但是發現這樣怎麼去維護lca呢.因為要求有序,所以我們可以用set來維護相同顏色的節點.如果把乙個點加入集合之後這個點前驅為x,後繼為y,那麼我們去修正,把xy的lca 1,然後x和當前點的lca 1,當前點和y的lca 1.from neighthorn by siriusren inclu...

七彩樹 HYSBZ 4771線段樹合併

本題是查詢乙個節點x的字樹內深度與其相差不超過d的節點有多少種顏色。如果單純考慮有多少個點,應該如何求?此時我們應該考慮如何維護深度在乙個區間內且是x的後代的資訊。我們可以每個節點用一顆以下標為權值的線段樹來維護 後面記為線段樹x 用線段樹合併來完成所有資訊的處理。但如何查詢深度在乙個區間裡的資訊呢...