【题目链接】

http://acm.hdu.edu.cn/showproblem.php?pid=6162

【算法】

离线树剖

我们知道,u到v路径上权值为[A,B]的数的和 = u到v路径上权值小于等于B的数的和 - u到v路径上权值小于等于(A-1)的数的和

不妨将询问拆开,离线计算答案即可

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + ; int i,n,m,u,v,now,timer,tot,cnt;
long long l,r;
int head[MAXN],size[MAXN],fa[MAXN],top[MAXN],
dep[MAXN],son[MAXN],dfn[MAXN];
long long ans[MAXN]; struct Edge
{
int to,nxt;
} e[MAXN<<];
struct info
{
int val,pos;
} a[MAXN];
struct Query
{
int u,v;
long long m;
int flag,id;
} q[MAXN<<]; struct SegmentTree
{
struct Node
{
int l,r;
long long sum;
} Tree[MAXN<<];
inline void build(int index,int l,int r)
{
int mid;
Tree[index] = (Node){l,r,};
if (l == r) return;
mid = (l + r) >> ;
build(index<<,l,mid);
build(index<<|,mid+,r);
}
inline void update(int index)
{
Tree[index].sum = Tree[index<<].sum + Tree[index<<|].sum;
}
inline void add(int index,int pos,long long val)
{
int mid;
if (Tree[index].l == Tree[index].r)
{
Tree[index].sum += val;
return;
}
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= pos) add(index<<,pos,val);
else add(index<<|,pos,val);
update(index);
}
inline long long query(int index,int l,int r)
{
int mid;
if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) return query(index<<,l,r);
else if (mid + <= l) return query(index<<|,l,r);
else return query(index<<,l,mid) + query(index<<|,mid+,r);
}
} T;
inline bool cmp1(info a,info b)
{
return a.val < b.val;
}
inline bool cmp2(Query a,Query b)
{
return a.m < b.m;
}
inline void add(int u,int v)
{
tot++;
e[tot] = (Edge){v,head[u]};
head[u] = tot;
}
inline void dfs1(int u)
{
int i,v;
size[u] = ;
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
if (fa[u] != v)
{
fa[v] = u;
dep[v] = dep[u] + ;
dfs1(v);
size[u] += size[v];
if (size[v] > size[son[u]]) son[u] = v;
}
}
}
inline void dfs2(int u,int tp)
{
int i,v;
top[u] = tp;
dfn[u] = ++timer;
if (son[u]) dfs2(son[u],tp);
for (i = head[u]; i; i = e[i].nxt)
{
v = e[i].to;
if (fa[u] != v && son[u] != v) dfs2(v,v);
}
}
inline long long query(int u,int v)
{
int tu = top[u],
tv = top[v];
long long ret = ;
while (tu != tv)
{
if (dep[tu] > dep[tv])
{
swap(u,v);
swap(tu,tv);
}
ret += T.query(,dfn[tv],dfn[v]);
v = fa[tv]; tv = top[v];
}
if (dfn[u] > dfn[v]) swap(u,v);
ret += T.query(,dfn[u],dfn[v]);
return ret;
} int main()
{ while (scanf("%d%d",&n,&m) != EOF)
{
timer = ;
tot = ;
for (i = ; i <= n; i++)
{
head[i] = ;
son[i] = ;
}
cnt = ;
memset(ans,,sizeof(ans));
for (i = ; i <= n; i++)
{
scanf("%lld",&a[i].val);
a[i].pos = i;
}
for (i = ; i < n; i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1();
dfs2(,);
T.build(,,timer);
for (i = ; i <= m; i++)
{
scanf("%d%d%lld%lld",&u,&v,&l,&r);
if (l > ) q[++cnt] = (Query){u,v,l-,,i};
q[++cnt] = (Query){u,v,r,,i};
}
sort(a+,a+n+,cmp1);
sort(q+,q+cnt+,cmp2);
now = ;
for (i = ; i <= cnt; i++)
{
while (now <= n && a[now].val <= q[i].m)
{
T.add(,dfn[a[now].pos],a[now].val);
now++;
}
if (q[i].flag == ) ans[q[i].id] -= query(q[i].u,q[i].v);
else ans[q[i].id] += query(q[i].u,q[i].v);
}
for (i = ; i < m; i++) printf("%lld ",ans[i]);
printf("%lld\n",ans[m]);
} return ; }

【HDU 6162】 Ch’s gift的更多相关文章

  1. 【 2017 Multi-University Training Contest - Team 9 && hdu 6162】Ch’s gift

    [链接]h在这里写链接 [题意] 给你一棵树,每个节点上都有一个权值. 然后给你m个询问,每个询问(x,y,a,b); 表示询问x->y这条路径上权值在[a,b]范围内的节点的权值和. [题解] ...

  2. 【HDU 2196】 Computer(树的直径)

    [HDU 2196] Computer(树的直径) 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 这题可以用树形DP解决,自然也可以用最直观的方法解 ...

  3. 【HDU 2196】 Computer (树形DP)

    [HDU 2196] Computer 题链http://acm.hdu.edu.cn/showproblem.php?pid=2196 刘汝佳<算法竞赛入门经典>P282页留下了这个问题 ...

  4. 【数位dp】【HDU 3555】【HDU 2089】数位DP入门题

    [HDU  3555]原题直通车: 代码: // 31MS 900K 909 B G++ #include<iostream> #include<cstdio> #includ ...

  5. 【HDU 5647】DZY Loves Connecting(树DP)

    pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS ...

  6. -【线性基】【BZOJ 2460】【BZOJ 2115】【HDU 3949】

    [把三道我做过的线性基题目放在一起总结一下,代码都挺简单,主要就是贪心思想和异或的高斯消元] [然后把网上的讲解归纳一下] 1.线性基: 若干数的线性基是一组数a1,a2,a3...an,其中ax的最 ...

  7. 【HDU 5145】 NPY and girls(组合+莫队)

    pid=5145">[HDU 5145] NPY and girls(组合+莫队) NPY and girls Time Limit: 8000/4000 MS (Java/Other ...

  8. 【hdu 1043】Eight

    [题目链接]:http://acm.hdu.edu.cn/showproblem.php?pid=1043 [题意] 会给你很多组数据; 让你输出这组数据到目标状态的具体步骤; [题解] 从12345 ...

  9. 【HDU 3068】 最长回文

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3068 [算法] Manacher算法求最长回文子串 [代码] #include<bits/s ...

随机推荐

  1. 【译】x86程序员手册03 - 2.1内存组织和分段

    2.1 Memory Organization and Segmentation 内存组织和分段 The physical memory of an 80386 system is organized ...

  2. Kafka 入门和 Spring Boot 集成

    目录 Kafka 入门和 Spring Boot 集成 标签:博客 概述 应用场景 基本概念 基本结构 和Spring Boot 集成 集成概述 集成环境 kafka 环境搭建 Spring Boot ...

  3. 关于java 关键字enum不识别的解决办法

    从别人那儿拷贝过来的myeclipse java工程,打开一看标红了一大片,仔细一看,原来是不识别enum关键字,这就有点尴尬了. 我自己重新建了一个java工程,测试了下,假如我在新建工程的时候选择 ...

  4. UITableview 兼容IOS6 和IOS7的方法

    1. TableVIew向下拉44像素  添加Auto layout 2. Extended edge 选择Under top bars 2. 在Viewdidload中添加代码 if ([[UIDe ...

  5. docker安装后出现Cannot connect to the Docker daemon

    启动docker service docker start docker安装后出现Cannot connect to the Docker daemon You need to add user in ...

  6. linux中快速查找文件

    在使用linux时,经常需要进行文件查找.其中查找的命令主要有find和grep.两个命令是有区的. 区别:(1)find命令是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访 ...

  7. java中关于数组的初始化

  8. 【Apache Kafka】二、Kafka安装及简单示例

    (一)Apache Kafka安装 1.安装环境与前提条件   安装环境:Ubuntu16.04   前提条件: ubuntu系统下安装好jdk 1.8以上版本,正确配置环境变量 ubuntu系统下安 ...

  9. LINUX C: 获取本地指定网卡的IP地址

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> ...

  10. json 添加 和删除两种方法

    <script> var test = { name: "name", age: "12" }; var countrys = { "ne ...