洛谷P3241 開店

2022-04-30 11:09:11 字數 3428 閱讀 7399

題意:紫妹和幽香是17歲的少女,喜歡可愛的東西。

解:動態點分治怎麼搞啊......

一開始想的是權值的限制直接外層權值線段樹就行了,關鍵是怎麼批量求距離。

jxl想的是樹上莫隊的方法,括號序列。然後發現當x和y在不同子樹的時候,x -> lca的距離是負的。

然後考慮lca。距離是d[x] + d[y] - 2d[lca],前面兩個都好求,主要是第三項。

稍稍思考一下,lca只可能是x到根路徑上的點。每個點作為lca的次數就是siz - siz[son]

所以可以轉為計算每條邊的貢獻。每條邊的貢獻就是它下面的子樹大小。這樣就可以做了。

具體來說,d[x] * cnt和∑d[y]可以用兩個字首和陣列求出。以離散化後的權值為下標。

然後建乙個以權值為版本的主席樹,線段樹上維護的是dfs序的該點的父邊的計算次數。

可以發現,按照權值我們每插入乙個點,就要對它到根的路徑進行修改。查詢的時候也是查詢x到根的路徑。所以我們必須寫樹剖了》_<

主席樹區間加區間查,使用標記永久化。

然後發現我之前以為的標記永久化都是假的......

具體來說,給乙個區間加的時候,它途中經過的區間都要加上相應的值,而標記只打在最後的區間。

查詢的時候,沿途記錄標記數量。到終點的時候,用終點的sum + 區間val * 標記數量即可。

如果修改在查詢上面,那麼你會把標記記錄下來,最後在終點區間加上。

如果修改在下,那麼你終點區間的sum已經加了那一次修改的影響。

然後這道毒瘤sb題就這樣a了...時間複雜度nlog2n。

1 #include 2 #include 3

4 typedef long

long

ll;5

const

int n = 150010, lm = 1e9, m = 30000010;6

7struct

edge edge[n << 1]; int

tp;10

11struct

node

16}node[n];

1718

inte[n], n, top[n], son[n], fa[n], pos[n], num, siz[n], x[n], deep[n], sum[n], id[n], val2[n], tot, rt[n], val[n];

19ll val[m], d[n], exval[n];

20int

ls[m], rs[m], exsum[n], tag[m];

2122 inline void add(int x, int y, int

z) 30

31void dfs_1(int x, int f)

40 d[y] = d[x] +edge[i].len;

41 val2[y] =edge[i].len;

42dfs_1(y, x);

43 siz[x] +=siz[y];

44if(siz[y] >siz[son[x]]) 47}

48return;49

}5051void dfs_2(int x, int f)

58for(int i = e[x]; i; i =edge[i].nex)

63dfs_2(y, y);64}

65return;66

}6768void add(int x, int &y, int l, int r, int l, int

r) 77 val[y] += sum[std::min(r, r)] - sum[std::max(l, l) - 1

];78

//printf("val %d = %lld += (%d %d) %d \n", y, val[y], std::min(r, r), std::max(l, l) - 1, sum[std::min(r, r)] - sum[std::max(l, l) - 1]);

79if(l <= l && r <=r)

83int mid = (l + r) >> 1;84

if(l <=mid)

87if(mid

90return;91

}9293 inline void insert(int x, int

id)

99return

;100

}101

102 ll ask(int x, int y, int l, int r, int l, int r, int tagx, int

tagy)

106 tagx +=tag[x];

107 tagy +=tag[y];

108int mid = (l + r) >> 1

;109 ll ans = 0

;110

if(l <=mid)

113if(mid

116return

ans;

117}

118119 ll ask(int l, int r, int

x) 126

return

ans;

127}

128129

intmain()

142for(int i = 1, x, y, z; i < n; i++)

147//

prework

148149 dfs_1(1, 0

);150 dfs_2(1, 1

);151 std::sort(x + 1, x + n + 1

);152

int temp = std::unique(x + 1, x + n + 1) - x - 1

;153

for(int i = 1; i <= n; i++)

159for(int i = 1; i <= temp; i++)

163for(int i = 1; i <= n; i++)

166 std::sort(node + 1, node + n + 1

);167

for(int i = 1; i <= n; i++)

170171 ll lastans = 0

;172

for(int i = 1, x, y, z; i <= q; i++)

179 l = std::lower_bound(x + 1, x + temp + 1, l) -x;

180 r = std::upper_bound(x + 1, x + temp + 1, r) - x - 1

;181

if(l >r)

185else

191}

192193

return0;

194 }

ac**

P3241 HNOI2015 開店 動態點分治

風見幽香有乙個好朋友叫八雲紫,她們經常一起看星星看月亮從詩詞歌賦談到人生哲學。最近她們靈機一動,打算在幻想鄉開一家小店來做生意賺點錢。這樣的想法當然非常好啦,但是她們也發現她們面臨著乙個問題,那就是店開在 面向什麼樣的人群。很神奇的是,幻想鄉的地圖是乙個樹形結構,幻想鄉一共有 n 個地方,編號為 1...

洛谷P5049 洛谷P5022 題解 旅行

原題 資料加強版 加強版 參考你谷題解 終於調過了 又是一如既往的申必錯誤 noi plus石錘了 原題的資料允許我們 o n 2 暴力斷邊,但是加強版的資料達到了 n log n 級別,我們必須在斷邊這一環節尋求更好的解法。考慮我們進入環後在何處回溯 根據繼續走環走到的點分類 設當前已經從 b 走...

洛谷練習P2279 P1346

2020年,人類在火星上建立了乙個龐大的基地群,總共有n個基地。起初為了節約材料,人類只修建了n 1條道路來連線這些基地,並且每兩個基地都能夠通過道路到達,所以所有的基地形成了乙個巨大的樹狀結構。如果基地a到基地b至少要經過d條道路的話,我們稱基地a到基地b的距離為d。由於火星上非常乾燥,經常引發火...