HDU 6162 Ch’s gift (线段树+树链剖分)
题意:给定上一棵树,每个树的结点有一个权值,有 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 (线段树+树链剖分)的更多相关文章
- 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两节 ...
- 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 ...
- HDU 6162 Ch’s gift (树剖 + 离线线段树)
Ch’s gift Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU 6162 Ch's gift(树链剖分+线段树)
题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...
- 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 ...
- 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
随机推荐
- 第七章 伪分布式安装hive,sqoop
第一部分:先讲这么去安装hive.先去hive官网下载,我这里以hive-0.12.0为例子. 前面第二章讲了安装hadoop,hbase实例,我们继续讲这么安装hive,先说下hive配置文件 一, ...
- docker 学习(十一) 镜像常用命令
1 创建账户,创建仓库 首先在dockerhub上有自己的账户,然后创建一个repository(如上图), 然后创建一个名字为robinfei/consumer的仓库. 2 本地镜像打标签(比 ...
- web页面取用户控件页面中服务器控件的值
用户控件页面后台: public string P_Name { get { return txt_P_name.Value; } set { txt_P_name.Value = value; } ...
- Shiro的学习
Apache Shiro 是 Java 的一个安全(权限)框架.它可以非常容易的开发出足够安全的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境 . Shiro 可以完成:认证 ...
- System.Security.Cryptography.CryptographicException: 系统找不到指定的文件
默认为false 改为true
- DOM笔录
文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...
- sql之分区域分段统计
sql之分区域分段统计 需求:在一个表中,有两列分别标记行政区划代码和家庭成员人数,需要得到不同乡镇的家庭成员人数在1-2人,3-4人,5-6人,6人以上的家庭数的表格 思路: 用case when对 ...
- mysql 乱码 utf8
my.ini [mysql]default-character-set=utf8 [mysqld]character-set-server=utf8 show variables like '%cha ...
- Adjacent Bit Counts(uvalive)
For a string of n bits x1, x2, x3,…, xn, the adjacent bit count of the string (AdjBC(x)) is given by ...
- 调用EF的存储过程报“存储区数据提供程序返回的数据读取器所具有的列数对于所请求的查询不够”问题
在运用Entity Framework调用存储过程的时候,遇到"调用EF的存储过程报"调用EF的存储过程报“存储区数据提供程序返回的数据读取器所具有的列数对于所请求的查询不够”问题 ...