感謝帶我飛的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 用線段樹合併來完成所有資訊的處理。但如何查詢深度在乙個區間裡的資訊呢...