P3676 小清新資料結構題

2022-04-07 20:39:52 字數 2654 閱讀 3477

p3676 小清新資料結構題

\[\sum_^\left(\sum_a_v\right)^2\\

\]後面那個東西就是子樹內兩兩權值乘積之和。

直接維護平方必然不行,都是維護一次然後搞一些操作間接維護的。

構造乙個函式

\[s=\sum a_i\\

c(rt)=\sum_^a_u\operatorname(rt,u)\\

\sum_^\sum_a_v = \sum_^a_u(\operatorname(rt,u)+1)=c(rt)+s\\

\]這個是可以維護的,修改查詢都可以 \(o(\log n)\)

\(s*(c(rt)+s)\) 會計算到每一顆子樹內每乙個結點和所有結點權值乘積。

多算的是跨過每一條邊的兩顆子樹內兩兩結點點權乘積,設為 \(d\) 。

可以發現修改乙個點的點權對於 \(d\) 的貢獻就是 \(\delta\times c(x)\) ,初始值可以直接 \(o(n)\) 算。

\[ans=s(c(rt)+s)-d

\]我是真的太遜了啊,不知道為啥你們都能理解 \(c(x)\) 的計算。

維護:\[r_1(u)=\sum_a_i\operatorname(u,v)\\

r_2(u)=\sum_a_i\operatorname(vt_u,v)\\

r_3(u)=\sum_a_i\\

\text

\]那麼

\[c(rt)=r_1(rt)+\sum_} r_1(vt_u)-r_2(u)+(r_3(vt_u)-r_3(u))\times \operatorname(vt_u,rt)

\]實現的時候判斷 \(vt_u\) 是否存在即可,只有 \(vt_u\) 存在才加後面那個貢獻。

誒誒誒?我 悟 了!確實很好理解啊,怎麼之前一直覺得很難理解呢???

我過了一年終於理解了/ll。這裡放一張自己畫的圖,應該很有幫助(以這題為例):

可以看到圖中分成了兩部分畫,所有 \(vt\) 是黑色中軸上的點,\(rt\) 是最下面那個子樹的根(三角形代表子樹)。

第一部分:\(r_1(rt)\) ,就是它子樹內的點對它的貢獻。

第二部分 \(\sum r_1(vt_u)-r_2(u)+(r_3(vt_u)-r_3(u))\times \operatorname(vt_u,rt)\) ,是子樹外的部分。我們每次讓綠色部分的點走到紫色結點,然後從紫色結點往下走到 \(rt\) 就能完成統計答案的任務了。

綠色部分走到紫色結點的貢獻就是紫色結點子樹內對它的貢獻,減去紅色部分對它的貢獻。

悟了之後,寫完過了編譯就ac了,真舒服。

#includeusing namespace std;

#define fi first

#define se second

#define mkp(x,y) make_pair(x,y)

#define pb(x) push_back(x)

#define sz(v) (int)v.size()

typedef long long ll;

typedef double db;

templatebool ckmax(t&x,t y)

#define rep(i,x,y) for(int i=x,i##end=y;i<=i##end;++i)

#define per(i,x,y) for(int i=x,i##end=y;i>=i##end;--i)

inline int read()

while(isdigit(ch))x=x*10+ch-'0',ch=getchar();

return f?x:-x;

}const int n=200005;

int n,q,a[n],rt;

ll s,d,r1[n],r2[n],r3[n],sum[n];

int fa[n],top[n],son[n],dep[n],siz[n];

int hed[n],et;

struct edgee[n<<1];

void adde(int u,int v)

namespace tree

d+=sum[u]*(s-sum[u]);

}void dfs2(int u,int tp)

}int lca(int x,int y)

int dis(int x,int y)

}using tree::lca;

using tree::dis;

namespace dfz

ckmax(mx[u],tsiz-siz[u]);

if(mx[u]

}bool qwq[n];

void solve(int x)

for(int i=hed[x];i;i=e[i].nx)

}ll calc(int x)

void upd(int x,int y)

}void change(int x,int y)

ll query(int x)

void build()

}signed main()

rep(i,1,n)a[i]=read(),s+=a[i];

tree::dfs1(1,0),tree::dfs2(1,1);

dfz::build();

while(q--)

return 0;

}

P3676 小清新資料結構題 (樹鏈剖分)

題目鏈結 題面 題解 見注釋 include include include include include include include include define ll long long define llu unsigned ll define int ll using namespac...

Luogu3676 小清新資料結構題

傳送門 維護兩個陣列,乙個是子樹的val和,乙個是子樹的val和的平方和 暴力更新,暴力查詢就可以獲得10分吐槽一波luogu的部分分 include define rg register define il inline define fill a,b memset a,b,sizeof a de...

洛谷 P3672 小清新簽到題 DP 排列

傳送門 題意 給定自然數n k x,你要求出第k小的長度為n的逆序對對數為x的1 n的排列 n le 300,k le 10 13 一下子想到hzc講過的dp 從小到大插入,後插入不會對前插入造成影響,f i j 表示 1.n 排列 j 個逆序對的方案數,列舉插在 然後從前向後選擇滿足要求的字典序最...