题意:给定上一棵树,每个树的结点有一个权值,有 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. lamp环境应用实践

    LAMP之apache2.4.33 apache工作模式 apache 常用工作模式有2种,区别在于 worker模式 1. 线程模式 2. 占用资源少 3. 稳定性略差 4. 并发大 prefork ...

  2. ALSA声卡笔记1---ALSA驱动框架

    1.声卡驱动程序sound.c (1)入口函数里通过register_chrdev()函数注册file_operations 结构体 (2)file_operations 结构体,里面只有open函数 ...

  3. 敌兵布阵hdu1166

    /* 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  4. canvas绘制矩形

    canvas绘制矩形 方法 fillRect(x, y, width, height) 画一个实心的矩形 clearRect(x, y, width, height) 清除一块儿矩形区域 stroke ...

  5. Tomcat官方文档关于数据源配置的内容

    虽然有网上有网友自己总结的文章,但说明得总是不够清晰,还是参考官方文档理解得比较透彻: http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html h ...

  6. Netty面试题

    1.BIO.NIO和AIO的区别? BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理.线程开销大. 伪异步IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源. N ...

  7. npm上传包

    npm上传包 向npm上传一个包是很容易的,只需要三步: 1.在npm官网注册一个账户,然后在cmd中登录账户 注:npm不要使用代理,直接连接 https://registry.npms.org/. ...

  8. HALCON中的算子大全(中英对照)

    HALCON中的算子大全(中英对照) Chapter 1 :Classification1.1 Gaussian-Mixture-Models1.add_sample_class_gmm功能:把一个训 ...

  9. sql开启xp_cmdshell

    sql开启xp_cmdshell sp_configure reconfigure go sp_configure reconfigure go

  10. 高并发下redis缓存穿透问题解决方案

    一.使用场景 我们在日常的开发中,经常会遇到查询数据列表的问题,有些数据是不经常变化的,如果想做一下优化,在提高查询的速度的同时减轻数据库的压力,那么redis缓存绝对是一个好的解决方案. 二.需求 ...