JZOJ4331 清華集訓模擬 樹

2022-05-31 17:51:10 字數 2254 閱讀 1058

給你一棵帶點權的樹,求將樹變成一堆不相交的鏈,而且這些鏈的權值和非負的方案數。

顯然這道題是個\(dp\)。

首先求個字首和\(sum\)。

為了後面講述方便,我這樣設:\(f_\)表示以\(i\)為根的子樹,其中某條鏈從\(x\)伸出到\(i\)的方案數,而且\(sum_x=j\)。

還有設\(g_i\)表示以\(i\)為根的,沒有伸出去的鏈的方案數。

顯然有這樣的轉移:

\[\prod g_i\to f_\\

f_\prod_ g_i\to f_x,j\]

\[f_ \to g_x \ (j-sum_\geq 0)\\

f_f_\prod_g_i\to g_x \ (j+k-2sum_x+a_x\geq 0)

\]如果直接這樣搞肯定會**。所以考慮用線段樹來維護\(f\)。

由於可能會出現\(g\)值為\(0\)的情況,所以不能直接用逆元來搞。

要維護個字首積和字尾積。

首先要求出重兒子,把重兒子作為第乙個兒子,然後線段樹合併之前也啟發式合併。

具體來說,我們欽定\(j。在合併的時候(設前面子樹合併出來的線段樹為\(a\),這個線段樹為\(b\))當前的兒子作為\(k\),遍歷\(b\)的所有葉子節點,並在\(a\)中區間詢問。這時候記得要乘上字尾積。將詢問出來的東西加在\(g_x\)中。

然後兩個合併在一起。記得在合併之前,整個\(a\)乘子樹的\(g_x\),整個\(b\)乘字首積

。搞完這個再合併。

最後你就會愉快地發現,所有子樹合併之後就是上面第二行式子。這樣只需要把第一行的加進去。第四行的式子已經計算完了,只需要再加上第乙個式子就可以了。

然而這不是題解的做法,作為乙個小蒟蒻,表示看不懂題解……

using namespace std;

#include #include #include #include #define n 100010

#define inf 1000000000

#define mo 1000000007

int n;

int a[n];

struct edge e[n*2];

int ne;

edge *last[n];

struct node *null;

struct node

inline void pushdown()

} inline void update()

} d[n*40];

int cnt;

node *rt[n];

inline node *newnode());}

void add(node *&t,int l,int r,int x,int c)

t->pushdown();

int mid=l+r>>1;

if (x<=mid)

add(t->l,l,mid,x,c);

else

add(t->r,mid+1,r,x,c);

t->update();

}int query(node *t,int l,int r,int st,int en)

node *merge(node *a,node *b)

int calc(node *t,int l,int r,node *rt,int bor)

int fa[n],sum[n],siz[n],hs[n];

int son[n],ns,pre[n],suc[n];

int g[n];

void dp(int x)

if (!hs[x])

son[ns=1]=hs[x];

pre[0]=1,pre[1]=g[hs[x]];

for (edge *ei=last[x];ei;ei=ei->las)

if (ei->to!=fa[x] && ei->to!=hs[x])

suc[ns+1]=1;

for (int i=ns;i>=1;--i)

suc[i]=(long long)suc[i+1]*g[son[i]]%mo;

rt[x]=rt[hs[x]];

for (int i=2;i<=ns;++i)

add(rt[x],-inf,inf,sum[x],pre[ns]);

g[x]+=query(rt[x],-inf,inf,sum[fa[x]],inf);

g[x]>=mo?g[x]-=mo:0;

}int main()

好多樹形dp都可以用線段樹合併來優化啊……

JZOJ4331 清華集訓模擬 樹

給你一棵帶點權的樹,求將樹變成一堆不相交的鏈,而且這些鏈的權值和非負的方案數。顯然這道題是個dpdp dp。首先求個字首和sum sumsu m。為了後面講述方便,我這樣設 fi,jf fi,j 表示以i ii為根的子樹,其中某條鏈從x xx伸出到i ii的方案數,而且sum x jsum x j ...

JZOJ 4330 清華集訓模擬 幾何題

這題的複雜度是o 106log 106 的fft 害怕.jpg 預處理cnt i j k 表示x,y,z的差為i,j,k的有多少對,首先,xi xj可以變成xi mx xj mx為最大xi 那麼每位都是非負數了,現在要做3維的多項式乘法,考慮用2mx進製儲存這三個數,壓在一起變乙個數,這樣就把3維變...

JZOJ4330 清華集訓模擬 幾何題

也懶得解釋題目大意了 正解居然是fft fftff t?不要看題目的那個式子這麼長,也不要在那個式子上下手。其實我們會發現,不同的 xi xj,yi y j,zi zj x i x j,y i y j,z i z j xi x j y i y j z i z j 並不多。如果我們求出每個三元組的出現...