HNOI2015 開店 樹鏈剖分,主席樹

2022-04-29 22:57:12 字數 1742 閱讀 6443

lg傳送門

蒟蒻表示不會動態澱粉質。

先把點按年齡排序, 設\(dis[i]\)表示\(i\)到根的距離。

把我們要算的東西稍微變下形:\(ans\)

\[= \sum \limits _ ^r (dis[i] + dis[u] - 2 * dis[lca(i, u)]

\]\[= \sum \limits _ ^r dis[i] + (r - l + 1) * dis[u] - 2 * \sum \limits _ ^r dis[lca(i, u)]

\]前面兩項都很容易算,主要是最後一項不太好弄,假設我們能快速求出\(\sum \limits _ ^n dis[lca(i, u)]\),那麼我們就可以套上乙個主席樹解決這個問題,考慮樹剖,對於每個點將這個點到根路徑上的點權值加一,維護每個點的權值乘以其父邊的權值的區間和,查詢的時候就算一下詢問點到根的路徑上線段樹所維護的資訊和就行了。

主席樹需要標記永久化。

//written by newbiechd

#include #include #include #include #define r register

#define i inline

#define b 1000000

#define l long long

using namespace std;

const int n = 150003;

char buf[b], *p1, *p2;

i char gc()

i int rd()

int s[n], dep[n], fa[n], lst[n], siz[n], son[n], dfn[n], top[n], rt[n], n, tim, t, tmp;

l dis[n], sum[n], val[n], ans;

struct node

node (int p, int d) : p(p), d(d) {}

}a[n];

struct segtree e[n << 7];

vector > g[n];

i int operator < (node x, node y)

i void swap(int &x, int &y)

void dfs1(int x, int f)

}void dfs2(int x, int t)

int insert(int k, int l, int r, int x, int y)

e[t].s += val[y] - val[x - 1];

r int m = (l + r) >> 1;

if (y <= m)

e[t].p = insert(e[k].p, l, m, x, y);

else

if (m < x)

e[t].q = insert(e[k].q, m + 1, r, x, y);

else

e[t].p = insert(e[k].p, l, m, x, m),

e[t].q = insert(e[k].q, m + 1, r, m + 1, y);

return t;

}l query(int k, int l, int r, int x, int y)

i void modify(int x)

i l calc(int x, int root)

int main()

return 0;

}

HNOI2015 開店 題解

目前只有開o2能過,stl的常數太大了,qwq 題意簡述,給你一棵樹,有點權與邊權,然後有很多詢問,每次詢問你點權在l r l r範圍內的點到給點點v v的距離之和。我們使用動態點分治來求取答案。先構建出點分樹,樹高肯定是在log nlog n級別內的,然後對於乙個分治點 重心 我們在上面記錄三個值...

HNOI2015實驗比較 樹型DP

我看了一下,網上好像沒有跟我一樣做法的,而且我根本學不會那個做法。那我只好發個部落格啦 做法也許有錯 有n n 個物品和 m role presentation style position relative m m個條件,每個條件表示 i i 的權值小於或等於 j role presentatio...

樹鏈剖分 樹鏈剖分講解

好了,這樣我們就成功解決了對樹上修改查詢邊權或點的問題。下面放上 vector v maxn int size maxn dep maxn val maxn id maxn hson maxn top maxn fa maxn 定義 int edge 1,num 1 struct tree e ma...