题意:给定上一棵树,每个树的结点有一个权值,有 m 个询问,每次询问 s, t ,  a, b,问你从 s 到 t 这条路上,权值在 a 和 b 之间的和。(闭区间)。

析:很明显的树链剖分,但是要用线段树来维护,首先先离线,然后按询问的 a 排序,每次把小于 a 的权值先更新上,然后再查询,这样就是区间求和了,算完小于a的,再算b的,最答案相减就好了。

代码如下:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <algorithm>
#include <vector>
#include <map>
#include <cctype>
#include <cmath>
#include <stack>
#include <sstream>
#include <list>
#include <assert.h>
#include <bitset>
#define debug() puts("++++");
#define gcd(a, b) __gcd(a, b)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define fi first
#define se second
#define pb push_back
#define sqr(x) ((x)*(x))
#define ms(a,b) memset(a, b, sizeof a)
#define sz size()
#define pu push_up
#define pd push_down
#define cl clear()
#define all 1,n,1
#define FOR(x,n) for(int i = (x); i < (n); ++i)
#define freopenr freopen("in.txt", "r", stdin)
#define freopenw freopen("out.txt", "w", stdout)
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> P;
const int INF = 0x3f3f3f3f;
const double inf = 1e20;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn = 1e5 + 10;
const LL mod = 1e9 + 7;
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};
int n, m;
const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline bool is_in(int r, int c) {
return r > 0 && r <= n && c > 0 && c <= m;
} struct Val{
int x, id;
};
Val a[maxn]; struct Edge{
int to, next;
};
Edge edge[maxn<<1];
int head[maxn<<1], cnt; void add(int u, int v){
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
} struct Query{
int s, t, a, b;
int id;
};
Query q[maxn]; inline bool cmpVal(const Val &lhs, const Val &rhs){
return lhs.x < rhs.x;
} inline bool cmpL(const Query &lhs, const Query &rhs){
return lhs.a < rhs.a;
} inline bool cmpR(const Query &lhs, const Query &rhs){
return lhs.b < rhs.b;
} int fa[maxn], top[maxn], p[maxn];
int pos, son[maxn], num[maxn], dep[maxn]; void init(){
cnt = 0; pos = 0;
ms(head, -1);
ms(son, -1);
} void dfs1(int u, int f, int d){
fa[u] = f; dep[u] = d;
num[u] = 1;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == f) continue;
dfs1(v, u, d+1);
num[u] += num[v];
if(son[u] == -1 || num[son[u]] < num[v]) son[u] = v;
}
} void dfs2(int u, int sp){
top[u] = sp;
p[u] = ++pos;
if(son[u] == -1) return ;
dfs2(son[u], sp);
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
} LL sum[maxn<<2]; void push_up(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
} void update(int M, int val, int l, int r, int rt){
if(l == r){ sum[rt] = val; return ; }
int m = l + r >> 1;
if(M <= m) update(M, val, lson);
else update(M, val, rson);
pu(rt);
} LL query(int L, int R, int l, int r, int rt){
if(L <= l && r <= R) return sum[rt];
int m = l + r >> 1;
LL ans = 0;
if(L <= m) ans = query(L, R, lson);
if(R > m) ans += query(L, R, rson);
return ans;
} LL solve(int u, int v){
int f1 = top[u], f2 = top[v];
LL ans = 0;
while(f1 != f2){
if(dep[f1] < dep[f2]){
swap(f1, f2);
swap(u, v);
}
ans += query(p[f1], p[u], all);
u = fa[f1];
f1 = top[u];
}
if(dep[u] > dep[v]) swap(u, v);
return ans += query(p[u], p[v], all);
} LL ansL[maxn], ansR[maxn]; int main(){
while(scanf("%d %d", &n, &m) == 2){
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);
add(u, v);
add(v, u);
}
dfs1(1, -1, 0);
dfs2(1, 1);
for(int i = 0; i < m; ++i){
scanf("%d %d %d %d", &q[i].s, &q[i].t, &q[i].a, &q[i].b);
--q[i].a;
q[i].id = i;
}
ms(sum, 0);
sort(a + 1, a + n + 1, cmpVal);
sort(q, q + m, cmpL);
int idx = 1;
for(int i = 0; i < m; ++i){
while(idx <= n && a[idx].x <= q[i].a) update(p[a[idx].id], a[idx].x, all), idx++;
ansL[q[i].id] = solve(q[i].s, q[i].t);
}
ms(sum, 0);
sort(q, q + m, cmpR);
idx = 1;
for(int i = 0; i < m; ++i){
while(idx <= n && a[idx].x <= q[i].b) update(p[a[idx].id], a[idx].x, all), idx++;
ansR[q[i].id] = solve(q[i].s, q[i].t);
}
for(int i = 0; i < m; ++i){
if(i) putchar(' ');
printf("%I64d", ansR[i]-ansL[i]);
}
printf("\n");
}
return 0;
}

  

HDU 6162 Ch’s gift (线段树+树链剖分)的更多相关文章

  1. HDU 6162 - Ch’s gift | 2017 ZJUT Multi-University Training 9

    /* HDU 6162 - Ch’s gift [ LCA,线段树 ] | 2017 ZJUT Multi-University Training 9 题意: N节点的树,Q组询问 每次询问s,t两节 ...

  2. 2017 Multi-University Training Contest - Team 9 1002&&HDU 6162 Ch’s gift【树链部分+线段树】

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  3. HDU 6162 Ch’s gift (树剖 + 离线线段树)

    Ch’s gift Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  4. HDU 6162 Ch's gift(树链剖分+线段树)

    题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...

  5. HDU 6162 Ch’s gift

    Mr. Cui is working off-campus and he misses his girl friend very much. After a whole night tossing a ...

  6. 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...

  7. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  8. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

  9. BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP

    题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...

随机推荐

  1. java基础-构建命令行运行的java程序简要注意

    今天编写了一个运行在服务端的java工具类,才发现自己以前很少关注运营方面的内容,导致在服务端部署一个java的工具变得异常困难,其实这也是自己对java的了解不够造成的. 首先,当代码编写完成之后, ...

  2. Go - 切片(Slice)

    定义 切片本身不是数组,它指向底层的数组或者数组的一部分.因此,可以使用Slice来处理变长数组的应用场景. Silice 是一种引用类型. 1.定义一个空的Slice package main im ...

  3. ALSA声卡08_从零编写之框架_学习笔记

    1.整体框架 (1)图示((DAI(全称Digital Audio Interface)接口)) 在嵌入式系统里面,声卡驱动是ASOC,是在ALSA驱动上封装的一层,包括以下三大块 (2)程序框架 m ...

  4. 【游记】noip2017酱油记

    2017-10-14:初赛 12:00:比赛时间14:30-16:30,由于比赛地点在二附中,我12点就坐上了地铁(无力吐槽,周六中午人还那么多,站了一路). 13:45:到了efz,所有人都被拦在了 ...

  5. small_vector

    folly/small_vector.h folly::small_vector<T,Int=1,...> is a sequence container that implements ...

  6. linux如何配置双机SSH信任然后双向免密码登陆

    linux如何配置双机SSH信任然后双向免密码登陆 www.111cn.net 更新:2015-01-14 编辑:edit02_lz 来源:转载 有时为了方便管理多台Linux主机,想实现双机之间信任 ...

  7. optparse模块

    optparse模块主要是用来对参数的记录,相对来说比较灵活, 例子代码如下: #!/usr/bin/env python from optparse import OptionParser usag ...

  8. C#并口操作

    using System;using System.Runtime.InteropServices;public class PortAccess { [DllImport("inpout3 ...

  9. 用letsencrypt搭建免费的https网站--nginx篇

    环境:阿里云服务器centos7.3,nignx,letsencrypt做免费的https证书 Let’s Encrypt官网:https://letsencrypt.org/ 1.服务器开放端口:4 ...

  10. MaperReduce实验

    目录 MaperReduce实现WordCount程序二次排序 前期准备 1. 工程结构 2. 编写自定义NewKey类 3. 编写WCMapper类 4. 编写WCReduer类 5. 编写作业描述 ...