HDU 6162 Ch’s gift(树链剖分+线段树)
来源:互联网 发布:喜马拉雅山攀登 知乎 编辑:程序博客网 时间:2024/06/05 21:32
题意:给你一颗树,每个节点有一个值,q次询问,每次询问u到v的路径上节点权值在a至b的节点的权值和。
n,q<=1e5
思路:可以离线处理,分别求出路径中<a的和,<=b的和,两者做差就是答案。
代码:
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int maxn = 1e5+5;int deep[maxn], fa[maxn], top[maxn], tree[maxn], pre[maxn], son[maxn], num[maxn];int n, q, tot;ll treeSum[maxn*4], ansL[maxn], ansR[maxn];vector<int> g[maxn];struct node1{ int x, id; bool operator < (const node1 &a) const { return x < a.x; }}a[maxn];struct node2{ int x, y, a, b, id;}op[maxn];bool cmp1(const node2 &a, const node2 &b){ return a.a < b.a;}bool cmp2(const node2 &a, const node2 &b){ return a.b < b.b;}void init(){ tot = 0; memset(son, 0, sizeof(son)); memset(num, 0, sizeof(num)); for(int i = 0; i <= n; i++) g[i].clear();}void dfs1(int u, int pre, int d){ deep[u] = d; fa[u] = pre; num[u] = 1; for(int i = 0, len = g[u].size(); i < len; i++) { int v = g[u][i]; if(v == pre) continue; dfs1(v, u, d+1); num[u] += num[v]; if(!son[v] || num[v] > num[son[u]]) son[u] = v; }}void dfs2(int u, int tp){ top[u] = tp; tree[u] = ++tot; pre[tree[u]] = u; if(!son[u]) return ; dfs2(son[u], tp); for(int i = 0, len = g[u].size(); i < len; i++) { int v = g[u][i]; if(v != son[u] && v != fa[u]) dfs2(v, v); }}void push_up(int root){ treeSum[root] = treeSum[root*2]+treeSum[root*2+1];}void update(int root, int l, int r, int pos, int val){ if(l == r) { treeSum[root] += val; return ; } int mid = (l+r)/2; if(pos <= mid) update(root*2, l, mid, pos, val); else update(root*2+1, mid+1, r, pos, val); push_up(root);}ll query(int root, int l, int r, int i, int j){ if(i <= l && j >= r) return treeSum[root]; int mid = (l+r)/2; ll res = 0; if(i <= mid) res += query(root*2, l, mid, i, j); if(j > mid) res += query(root*2+1, mid+1, r, i, j); return res;}ll ask(int x, int y){ int f1 = top[x], f2 = top[y]; ll ans = 0; while(f1 != f2) { if(deep[f1] < deep[f2]) swap(f1, f2), swap(x, y); ans += query(1, 1, n, tree[f1], tree[x]); x = fa[f1], f1 = top[x]; } ans += (deep[x]>deep[y]) ? query(1, 1, n, tree[y], tree[x]) : query(1, 1, n, tree[x], tree[y]); return ans;}int main(void){ while(cin >> n >> q) { init(); for(int i = 1; i <= n; i++) scanf("%d", &a[i].x), a[i].id = i; for(int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); g[u].push_back(v); g[v].push_back(u); } dfs1(1, 0, 1); dfs2(1, 1); for(int i = 1; i <= q; i++) scanf("%d%d%d%d", &op[i].x, &op[i].y, &op[i].a, &op[i].b), op[i].id = i; sort(a+1, a+1+n); //L memset(treeSum, 0, sizeof(treeSum)); sort(op+1, op+1+q, cmp1); for(int i = 1, j = 1; i <= q; i++) { while(j <= n && a[j].x < op[i].a) { update(1, 1, n, tree[a[j].id], a[j].x); j++; } ansL[op[i].id] = ask(op[i].x, op[i].y); } //R memset(treeSum, 0, sizeof(treeSum)); sort(op+1, op+1+q, cmp2); for(int i = 1, j = 1; i <= q; i++) { while(j <= n && a[j].x <= op[i].b) { update(1, 1, n, tree[a[j].id], a[j].x); j++; } ansR[op[i].id] = ask(op[i].x, op[i].y); } for(int i = 1; i <= q; i++) { if(i != 1) printf(" "); printf("%lld", ansR[i]-ansL[i]); } puts(""); } return 0;}
阅读全文
2 0
- HDU 6162 Ch’s gift(树链剖分+线段树)
- Hdu 6162 Ch’s gift【思维+树链剖分+线段树】
- hdu-6162 Ch’s gift(树链剖分)
- hdu 6162 Ch’s gift【树链剖分】
- hdu-6162 Ch’s gift 主席树
- hdu 6162 Ch’s gift(主席树+树链剖分)
- hdu 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch’s gift
- HDU 6162 Ch's gift
- HDU 6162 Ch’s gift
- Ch’s gift HDU
- Ch’s gift HDU
- Ch’s gift HDU
- hdu 6162 Ch’s gift 树链剖分 + 离线查询
- hdu 6162 Ch’s gift(主席树)
- HDU 6162 Ch’s gift(LCA)
- hdu 6162 Ch’s gift(树链刨分)
- 将字符串的图片展示到webview上
- OpenJ_Bailian
- iDT算法
- 有关Vb的CodeDom动态编译
- Oracle10g RAC (OCFS2)开启关闭及日常检查
- HDU 6162 Ch’s gift(树链剖分+线段树)
- 关注民生民情——华北水利水电大学“情艺”国情社情调查团
- 回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议
- Class.forName()用法详解
- NLP深度学习 —— CS224学习笔记3
- 状态码收集
- JSONP实现跨域请求JSON数据
- 【tomcat】tomcat常见操作记录
- 日常(抗日神剧_扫雷)