题意:给定上一棵树,每个树的结点有一个权值,有 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. VC6.0打开文件是卡死的解决办法

    删除工程目录下的 .ncb .opt 文件,然后就OK了!

  2. WePY 在手机充值小程序中的应用与实践

    wepyjs 发布了两个月了,中间经历了很多版本更新,也慢慢开始有一些用户选择 wepyjs 作为开发框架来开发小程序,比如一些线上小程序. 以及一些来自网上的 wepyjs 的相关资源: demo源 ...

  3. js 的eval()方法 计算某个字符串,并执行其中的的 JavaScript 代码;

    定义和用法 eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 Java ...

  4. Eclipse将控制台输出信息保存为文件

    当你在Eclipse中 running/debugging一个应用程序的时候,有关该应用程序的运行调试信息及日志信息都会输出到控制台(console )显示,但是Eclipse只会显示最后一部分的日志 ...

  5. Elasticsearch-PHP 处理JSON数组和对象

    PHP中处理JSON数组和对象 客户端有一些混淆的资源是围绕着JSON的数组和对象,以及如何在PHP中指定它们.特别是,问题是由空对象和空数组导致的.这篇文章回告诉你一些在Elasticsearch ...

  6. iOS 布局之 Springs and Struts

    “springs and struts” 模式,就是代码中的autosizing masks布局控制. autosizing mask决定了一个view会发生什么当它的superview 改变大小的时 ...

  7. Android开发实战之ViewPager实现向导界面

    当我们更新应用,或者第一次进入应用时都会有一个向导界面,介绍这个app的内容和使用方式. 如果你细心你会发现其实这就是个viewpager,本篇博文将介绍应用的向导界面是如何制作的.希 望本篇博文对你 ...

  8. 使用CMD命令行来对MySQL数据库执行迁移、备份、恢复

    1. 导出数据库数据   "C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqldump.exe" -u root -p123abc ...

  9. C++——堆、栈、静态存储区

      栈 堆 静态存储区 生命周期 函数结束即释放 new,malloc开辟,delete,free释放 释放前,一直存在 最长,程序退出才释放   程序.局部变量 new,malloc申请的空间,用于 ...

  10. MAXOS 进程管理

    ps -ef|grep +程序名 注意进程名区分大小写 linux上进程有5种状态:1. 运行(正在运行或在运行队列中等待)2. 中断(休眠中, 受阻, 在等待某个条件的形成或接受到信号)3. 不可中 ...