日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

「2017 山东一轮集训 Day5」距离

發布時間:2025/7/14 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「2017 山东一轮集训 Day5」距离 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
/* 寫完開店再寫這個題目頓時神清氣爽, 腰也不疼了, 眼也不花了首先考慮將詢問拆開, 就是查詢一些到根的鏈和點k的關系根據我們開店的結論, 一個點集到一個定點的距離和可以分三部分算 那么就很簡單了吧QAQ, 在樹上可持久化弄一下 */#include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<iostream> #define ll long long #define mmp make_pair #define M 200010 using namespace std; int read() {int nm = 0, f = 1;char c = getchar();for(; !isdigit(c); c = getchar()) if(c == '-') f = -1;for(; isdigit(c); c = getchar()) nm = nm * 10 + c - '0';return nm * f; }int type, n, q, sz[M], son[M], fa[M], top[M], dfn[M], ver[M], dft, cnt, p[M], deep[M]; ll dis[M], sum[M], w[M], ans; vector<pair<int,int> > to[M]; int lc[20000100], rc[20000100], v[20000100], rt[M]; ll t[20000100];void dfs(int now, int f) {deep[now] = deep[f] + 1;sz[now] = 1;fa[now] = f;for(int i = 0; i < to[now].size(); i++){int vj = to[now][i].first, v = to[now][i].second;if(vj == f) continue;dis[vj] = dis[now] + v;ver[vj] = v; // deep[vj] = deep[now] + 1;dfs(vj, now);if(sz[vj] > sz[son[now]]) son[now] = vj;sz[now] += sz[vj];} }void dfs(int now) {dfn[now] = ++cnt;w[cnt] = ver[now];if(son[now]){top[son[now]] = top[now];dfs(son[now]);}for(int i = 0; i < to[now].size(); i++){int vj = to[now][i].first;if(vj == fa[now] || vj == son[now]) continue;top[vj] = vj;dfs(vj);} }void modify(int last, int &now, int l, int r, int ln, int rn) {now = ++cnt;lc[now] = lc[last], rc[now] = rc[last], t[now] = t[last], v[now] = v[last];if(l == ln && r == rn){v[now]++;return;}t[now] += w[rn] - w[ln - 1];int mid = (l + r) >> 1;if(ln > mid) modify(rc[last], rc[now], mid + 1, r, ln, rn);else if(rn <= mid) modify(lc[last], lc[now], l, mid, ln, rn);else modify(lc[last], lc[now], l, mid, ln, mid), modify(rc[last], rc[now], mid + 1, r, mid + 1, rn); }ll query(int now, int l, int r, int ln, int rn) {ll ans = 1ll * (w[rn] - w[ln - 1]) * v[now];if(l == ln && r <= rn) return ans + t[now];int mid = (l + r) >> 1;if(rn <= mid) return ans + query(lc[now], l, mid, ln, rn);else if(ln > mid) return ans + query(rc[now], mid + 1, r, ln, rn);else return ans + query(lc[now], l, mid, ln, mid) + query(rc[now], mid + 1, r, mid + 1, rn); }void Modify(int &now, int x) {for(; top[x] != 1; x = fa[top[x]]) modify(now, now, 1, n, dfn[top[x]], dfn[x]);modify(now, now, 1, n, dfn[1], dfn[x]); }void work(int now) {rt[now] = rt[fa[now]];Modify(rt[now], p[now]);sum[now] = dis[p[now]] + sum[fa[now]];for(int i = 0; i < to[now].size(); i ++){int vj = to[now][i].first;if(vj == fa[now]) continue;work(vj);} }ll Query(int x, int k) {if(k == 0) return 0; // cout << k << " ";ll ans = sum[x];ans += dis[k] * deep[x];for(; top[k] != 1; k = fa[top[k]]) ans -= 2ll * query(rt[x], 1, n, dfn[top[k]], dfn[k]);ans -= 2ll *query(rt[x], 1, n, dfn[1], dfn[k]); // cout << x << " " << ans << "!!!!!!!\n";return ans; }int LCA(int a, int b) {while(top[a] != top[b]){if(deep[top[a]] < deep[top[b]]) swap(a, b);a = fa[top[a]];}if(deep[a] > deep[b]) swap(a, b);return a; }int main() {type = read(); n = read(), q = read();for(int i = 1; i < n; i++){int vi = read(), vj = read(), v = read();to[vi].push_back(mmp(vj, v));to[vj].push_back(mmp(vi, v));}for(int i = 1; i <= n; i++) p[i] = read();dfs(1, 0);top[1] = 1;dfs(1);for(int i = 1; i <= n; i++) w[i] += w[i - 1];work(1);while(q--){ll vi = read() ^ ans, vj = read() ^ ans, k = read() ^ ans;int l = LCA(vi, vj);ans = Query(vi, k) + Query(vj, k) - Query(l, k) - Query(fa[l], k);cout << ans << "\n";ans *= type;}return 0; }

轉載于:https://www.cnblogs.com/luoyibujue/p/10620465.html

總結

以上是生活随笔為你收集整理的「2017 山东一轮集训 Day5」距离的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。