P3241 HNOI2015 開店 動態點分治

2022-07-20 04:18:09 字數 3106 閱讀 4909

風見幽香有乙個好朋友叫八雲紫,她們經常一起看星星看月亮從詩詞歌賦談到人生哲學。最近她們靈機一動,打算在幻想鄉開一家小店來做生意賺點錢。

這樣的想法當然非常好啦,但是她們也發現她們面臨著乙個問題,那就是店開在**,面向什麼樣的人群。很神奇的是,幻想鄉的地圖是乙個樹形結構,幻想鄉一共有 \(n\)個地方,編號為 \(1\) 到\(n\) 被\(n-1\) 條帶權的邊連線起來。每個地方都住著乙個妖怪,其中第\(i\) 個地方的妖怪年齡是 \(x_i\) 。

妖怪都是些比較喜歡安靜的傢伙,所以它們並不希望和很多妖怪相鄰。所以這個樹所有頂點的度數都小於或等於 \(3\)。妖怪和人一樣,興趣點隨著年齡的變化自然就會變化,比如我們的\(18\) 歲少女幽香和八雲紫就比較喜歡可愛的東西。幽香通過研究發現,基本上妖怪的興趣只跟年齡有關,所以幽香打算選擇乙個地方\(u\) (\(u\) 為編號),然後在\(u\)開一家面向年齡在\(l\) 到\(r\) 之間(即年齡大於等於\(l\) 小於等於\(r\) )的妖怪的店。

也有可能\(u\) 這個地方離這些妖怪比較遠,於是幽香就想要知道所有年齡在\(l\) 到\(r\) 之間的妖怪,到點\(u\) 的距離的和是多少(妖怪到\(u\) 的距離是該妖怪所在地方到\(u\) 的路徑上的邊的權之和),幽香把這個稱為這個開店方案的方便值。

幽香她們還沒有決定要把店開在**,八雲紫倒是準備了很多方案,於是幽香想要知道,對於每個方案,方便值是多少呢。

第一行三個用空格分開的數\(n,q\) 和\(a\) ,表示樹的大小、開店的方案個數和妖怪的年齡上限。

第二行\(n\) 個用空格分開的數\(x_1,x_2,\ldots,x_n;\)xi 表示第\(i\) 個地點妖怪的年齡,滿足\(0\le x_i\lt a\) 。(年齡是可以為\(0\)的,例如剛出生的妖怪的年齡為\(0\) 。)

接下來\(n-1\) 行,每行三個用空格分開的數\(a\) 、\(b\) 、\(c\) ,表示樹上的頂點\(a\) 和\(b\) 之間有一條權為\(c(1\le c\le1000)\)的邊,\(a\) 和\(b\) 是頂點編號。

接下來\(q\) 行,每行三個用空格分開的數\(u,a,b\) 。

對於這\(q\) 行的每一行,用\(a,b,a\) 計算出\(l\) 和\(r\) ,表示詢問」在地方\(u\) 開店,面向妖怪的年齡區間為\([l,r]\) 的方案的方便值是多少「。

對於其中第\(1\) 行,\(l\) 和\(r\) 的計算方法為:\(l\) = min(\(a\) % \(a\),\(b\) % \(a\)),\(r\) = max(\(a\) % \(a\),\(b\) % \(a\)) 。

對於第\(2\) 到第\(q\) 行,假設前一行得到的方便值為\(ans\) ,那麼當前行的\(l\) 和\(r\) 計算方法為: $l=min((a+ans)%a,(b+ans) %a),r=max((a+ans) %a,(b+ans) %a) 。

對於每個方案,輸出一行表示方便值。

10 10 10

0 0 7 2 1 4 7 7 7 9

1 2 270

2 3 217

1 4 326

2 5 361

4 6 116

3 7 38

1 8 800

6 9 210

7 10 278

8 9 8

2 8 0

9 3 1

8 0 8

4 2 7

9 7 3

4 7 0

2 2 7

3 2 1

2 3 4

1603 

957

7161

9466

3232

5223

1879

1669

1282

0

滿足\(n\le1.5*10^5,q\le2*10^5\) 。對於所有資料,滿足 \(a<=10^9\)

動態點分治

建立點分樹

每個點維護4個vector,乙個是自己子樹的age(有序加入),乙個是對應的dis字首和,我們考慮在age上二分找到l,r, 用這個下標在dis上收集ans

還有兩個陣列類似,記錄對父親的貢獻

先在點分樹讓上把四個vector預處理出來,為了保證age有序,我們先把點按age從小到大排序,在更新

然後在點分樹上統計貢獻就行,注意卡二分邊界

#include#define ll long long

ll in()

const int maxn = 2e5 + 10;

struct node

void *operator new (size_t)

};ll n, q, a;

using std::vector;

vectortofadis[maxn], tofaage[maxn], dis[maxn], age[maxn];

int siz[maxn], maxsiz[maxn], root, f[maxn][26], sum, rt, u[maxn], dep[maxn];

ll d[maxn][26], val[maxn];

node *head[maxn];

bool vis[maxn];

void add(int from, int to, ll dis)

void init()

}void getroot(int x, int fa)

maxsiz[x] = std::max(maxsiz[x], sum - siz[x]);

if(maxsiz[x] < maxsiz[root]) root = x;

}void build(int x)

} void build()

void dfs(int x, int fa)

}void beizeng()

}ll lca(int x, int y)

bool cmp(const int &a, const int &b)

void predoit() }}

ll calc(int pos, ll l, ll r)

return ans;

}

void query()

}int main()

洛谷P3241 開店

題意 紫妹和幽香是17歲的少女,喜歡可愛的東西。解 動態點分治怎麼搞啊.一開始想的是權值的限制直接外層權值線段樹就行了,關鍵是怎麼批量求距離。jxl想的是樹上莫隊的方法,括號序列。然後發現當x和y在不同子樹的時候,x lca的距離是負的。然後考慮lca。距離是d x d y 2d lca 前面兩個都...

HNOI2015 開店 題解

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

HNOI2015 開店 樹鏈剖分,主席樹

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 d...