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两节点之间的路径上点权值在[a,b]之间的点权总和
分析:
求出每个询问的LCA,然后离线
按dfs顺序更新树状数组,即某点处树状数组中存的值为其所有祖先节点的值
每个点处对答案的贡献为:
当其为第 i 个 lca 时, ans[i] -= 2 * query(a,b) , 再特判该节点
当其为第 i 个 s,t 时, ans[i] += query(a,b)
*/
#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N = 1e5+5;
typedef pair<int, int> P;
vector<int> G[N];//存边
vector<P> QQ[N];
int a[N], b[N*4], cnt, n, Q;
struct Query {
int s, t, lca, a, b;
}q[N];
void addedge(int u, int v) {
G[u].push_back(v);
}
namespace LCA {
struct Query {
int v, q;
}; vector <Query> query[N];//存每个点的询问
int ans[N], f[N], vis[N];
int sf(int x) {
return x == f[x] ? x : f[x] = sf(f[x]);
}
void init() {
memset(ans, -1, sizeof(ans));
for (int i = 0; i < N; i++) {
vis[i] = 0; f[i] = i; query[i].clear();
}
}
void adq(int u, int v, int id) {//添加询问
query[u].push_back(Query{v, id});
query[v].push_back(Query{u, id});
}
void LCA(int u) {
f[u] = u, vis[u] = 1;
for (auto& x : query[u]) {
if (vis[x.v] && ans[x.q] == -1)
ans[x.q] = sf(x.v);
}
for (auto& v : G[u]) {
if (vis[v]) continue;
LCA(v);
f[v] = u;
}
}
}
void init2()
{
cnt = 0;
for (int i = 1; i <= n; i++) b[++cnt] = a[i];
for (int i = 1; i <= Q; i++)
{
b[++cnt] = q[i].a;
b[++cnt] = q[i].b;
}
sort(b+1, b+cnt+1);
cnt = unique(b+1, b+cnt+1) - (b+1);
for (int i = 1; i <= n; i++)
a[i] = lower_bound(b+1, b+cnt+1, a[i]) - b;
for (int i = 1; i <= Q; i++)
{
q[i].a = lower_bound(b+1, b+cnt+1, q[i].a) - b;
q[i].b = lower_bound(b+1, b+cnt+1, q[i].b) - b;
}
}
LL ans[N], c[N<<4];
void modify(int x, LL num){
while (x <= cnt) c[x] += num, x += x&-x;
}
LL sum(int x) {
LL s = 0;
while (x) s += c[x], x -= x&-x;
return s;
}
void init()
{
memset(c, 0, sizeof(c));
for (int i = 0; i < N; i++) G[i].clear();
for (int i = 0; i < N; i++) QQ[i].clear();
memset(ans, 0, sizeof(ans));
}
void dfs(int u, int pre)
{
modify(a[u], b[a[u]]);
LL tmp;
for (auto & qq : QQ[u])
{
tmp = sum(q[qq.first].b) - sum(q[qq.first].a-1);
if (qq.second == -1)
{
ans[qq.first] -= 2*tmp;
if (a[u] >= q[qq.first].a && a[u] <= q[qq.first].b)
ans[qq.first] += b[a[u]];
}
else
{
ans[qq.first] += tmp;
}
}
for (auto&v: G[u])
{
if (v == pre) continue;
dfs(v, u);
}
modify(a[u], -b[a[u]]);
}
int main()
{
int u, v;
while (~scanf("%d%d", &n, &Q))
{
init();
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i < n; i++)
{
scanf("%d%d", &u, &v);
addedge(u, v); addedge(v, u);
}
for (int i = 1; i <= Q; i++)
scanf("%d%d%d%d", &q[i].s, &q[i].t, &q[i].a, &q[i].b);
init2();
LCA::init();
for (int i = 1; i <= Q; i++) LCA::adq(q[i].s, q[i].t, i);
LCA::LCA(1);
for (int i = 1; i <= Q; i++)
{
q[i].lca = LCA::ans[i];
QQ[q[i].lca].push_back(P(i, -1));
QQ[q[i].s].push_back(P(i, 1));
QQ[q[i].t].push_back(P(i, 1));
}
dfs(1, 1);
for (int i = 1; i < Q; i++) printf("%lld ", ans[i]);
printf("%lld\n", ans[Q]);
}
}
HDU 6162 - Ch’s gift | 2017 ZJUT Multi-University Training 9的更多相关文章
- 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 ...
- 2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162 题意:给出一棵树的链接方法,每个点都有一个数字,询问U->V节点经过所有路径中l < ...
- 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 ...
- HDU 6162 Ch's gift(树链剖分+线段树)
题意: 已知树上的每个节点的值和节点之间的关系建成了一棵树,现在查询节点u到节点v的最短路径上的节点值在l到r之间的节点值的和. 思路: 用树链剖分将树映射到线段树上,线段树上维护3个值,max,mi ...
- HDU 6162 Ch’s gift (线段树+树链剖分)
题意:给定上一棵树,每个树的结点有一个权值,有 m 个询问,每次询问 s, t , a, b,问你从 s 到 t 这条路上,权值在 a 和 b 之间的和.(闭区间). 析:很明显的树链剖分,但是要用 ...
- HDU 6170 - Two strings | 2017 ZJUT Multi-University Training 9
/* HDU 6170 - Two strings [ DP ] | 2017 ZJUT Multi-University Training 9 题意: 定义*可以匹配任意长度,.可以匹配任意字符,问 ...
- L - Ch’s gift HDU - 6162
Ch’s gift Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- HDU 6168 - Numbers | 2017 ZJUT Multi-University Training 9
/* HDU 6168 - Numbers [ 思维 ] | 2017 ZJUT Multi-University Training 9 题意: .... 分析: 全放入multiset 从小到大,慢 ...
随机推荐
- heroku 的用法
heroku 安装cli npm install -g heroku ubuntu 下 sudo snap install --classic heroku 安装 npm init -y heroku ...
- 关于Python编码这一篇文章就够了
概述 在使用Python或者其他的编程语言,都会多多少少遇到编码错误,处理起来非常痛苦.在Stack Overflow和其他的编程问答网站上,UnicodeDecodeError和UnicodeEnc ...
- 二进制知识(java中的位操作)
文章目录 前言 机器数 真值 原码 反码 补码 计算机中保存的都是补码 位操作 强制转换,精度丢失 前言 讲二进制的东西,必须要说明是多少位机器,八位机上的 1000 1000 和 十六位机上的 10 ...
- 17 SUMIF函数、countif函数、averagif函数
情景 按买家求他们的消费各是多少. 可以考虑使用分类汇总来做,但这里我们使用函数sumif来做. SUMIF函数 格式:=SUMIF(条件列表,匹配条件,数据区) 该函数这样理解:按照匹配条件,从条件 ...
- PAT(B) 1069 微博转发抽奖(Java)
题目链接:1069 微博转发抽奖 (20 point(s)) 题目描述 小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包.请你编写程序帮助他确 ...
- 2.33模型--去除字符串两头空格.c
[注:本程序验证是使用vs2013版] #include <stdio.h> #include <stdlib.h> #include <string.h> #pr ...
- python 流程判断
import getpass# print("hello word") ## name= 'pangxiao'# mix_name=name# print(mix_name,nam ...
- 记录MindSphere On Cloud Foundry的一次尝试过程
试验背景: 开始时间:2019年12月11日 结束时间:2019年12月13日 自己编写一个后台程序,尝试推送到Cloud Foundry上,并开放从MindSphere以外访问的权限. 程序实现以下 ...
- 本地安装SQL Server 2017 Express和Microsoft SQL Server Management Studio 18.1
sqlserver下载链接:https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 这个安装的是免费版的Express,当然也可 ...
- js 遍历树的层级关系的实现
1.遍历树的层级关系 1)先整理数据 2)找到id和数据的映射关系 3)然后找到父节点的数据,进行存储 test() { const list = [ { id: ", parentId: ...