2017多校第9场 HDU 6162 Ch’s gift 树剖加主席树
2024-08-24 18:58:14
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6162
题意:给出一棵树的链接方法,每个点都有一个数字,询问U-》V节点经过所有路径中l < = x < = r的数字和
解法:主席树维护区间和,树剖查询,复杂度nloglog。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
const int maxm = 40*maxn;
typedef long long LL;
int T[maxn];
int lson[maxm],rson[maxm];
LL sum[maxm];
int clk,M;
int newnode(){
clk++;
lson[clk]=rson[clk]=sum[clk]=0;
return clk;
}
void update(int &now, int pre, int L, int R, int pos, int val)
{
now = newnode();
lson[now] = lson[pre];
rson[now] = rson[pre];
sum[now] = sum[pre] + val;
if(L!=R){
int mid=(L+R)>>1;
if(pos<=mid) update(lson[now],lson[pre],L,mid,pos,val);
else update(rson[now],rson[pre],mid+1,R,pos,val);
}
}
LL query(int rt, int L, int R, int l, int r){
if(l<=L&&R<=r){
return sum[rt];
}
else{
int mid = (L+R)>>1;
LL ret = 0;
if(l <= mid) ret += query(lson[rt], L, mid, l, r);
if(mid < r) ret += query(rson[rt], mid+1, R, l, r);
return ret;
}
}
struct edge{
int to,next;
}E[maxn*2];
int head[maxn],edgecnt,tim;
int siz[maxn],top[maxn],son[maxn],dep[maxn];
int fa[maxn],tid[maxn],Rank[maxn],val[maxn];
void init(){
edgecnt=tim=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
clk=M=0;
lson[clk]=rson[clk]=sum[clk]=0;
}
void add(int u, int v){
E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
}
void dfs1(int u, int pre, int d){
dep[u]=d;
fa[u]=pre;
siz[u]=1;
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=pre){
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u, int tp){
top[u]=tp;
tid[u]=++tim;
Rank[tid[u]]=u;
if(son[u]==-1) return;
dfs2(son[u],tp);
for(int i=head[u];~i;i=E[i].next){
int v=E[i].to;
if(v!=son[u]&&v!=fa[u]){
dfs2(v,v);
}
}
}
int LCA(int u, int v)
{
int ret;
while(true)
{
if(top[u] == top[v])
{
ret = dep[u] < dep[v] ? u : v;
break;
}
else if(dep[top[u]] > dep[top[v]])
u = fa[top[u]];
else v = fa[top[v]];
}
return ret;
}
int t[maxn];
LL query(int u, int v, int a, int b)
{
a = lower_bound(t + 1, t + 1 + M, a) - t - 1;
b = upper_bound(t + 1, t + 1 + M, b) - t - 1;
if(b == 0)
return 0;
LL ret = 0;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u, v);
ret += query(T[tid[u]], 1, M, 1, b);
ret -= query(T[tid[top[u]] - 1], 1, M, 1, b);
if(a)
{
ret -= query(T[tid[u]], 1, M, 1, a);
ret += query(T[tid[top[u]] - 1], 1, M, 1, a);
}
u = fa[top[u]];
}
if(dep[u] < dep[v])
swap(u, v);
ret += query(T[tid[u]], 1, M, 1, b);
ret -= query(T[tid[v] - 1], 1, M, 1, b);
if(a)
{
ret -= query(T[tid[u]], 1, M, 1, a);
ret += query(T[tid[v] - 1], 1, M, 1, a);
}
return ret;
}
int main()
{
int n,m;
while(~scanf("%d %d",&n,&m))
{
init();
for(int i=1; i<=n; i++){
scanf("%d", &val[i]);
t[i]=val[i];
}
for(int i=1; i<n; i++){
int u,v;
scanf("%d %d", &u,&v);
add(u, v);
add(v, u);
}
dfs1(1,0,0);
dfs2(1,1);
sort(t+1,t+n+1);
M = unique(t+1, t+n+1)-t-1;
for(int i=1; i<=n; i++) val[i] = lower_bound(t+1, t+1+M, val[i])-t;
for(int i=1; i<=n; i++){
T[i] = T[i-1];
update(T[i],T[i],1,M,val[Rank[i]],t[val[Rank[i]]]);
}
for(int i=1; i<=m; i++){
int u,v,x,y;
scanf("%d %d %d %d", &u,&v,&x,&y);
LL ret = query(u,v,x,y);
printf("%lld", ret);
if(i == m){
printf("\n");
}
else{
printf(" ");
}
}
}
return 0;
}
最新文章
- 实战 ASP.NET Web API
- 如何合并多个PPT
- ruby HTTPS请求
- andriod前端传来经度 纬度 坐标 来查询数据库坐标周围500M内的类数据
- 自动备份文件到GITHUB的方法
- ENVI软件操作【数据显示操作——Overlay菜单操作】
- java 中的volatile
- fancybox的配置项
- html、css、js文件加载顺序及执行情况
- Java虚拟机类加载机制——案例分析
- 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrollTo和scrollBy两个方法
- java:线程的简单控制方法
- MQ-传输方式Topic和Queue的对比
- Asp.Net Mvc5 之Controller
- Java GC 概念摘要
- 将.lib库文件转换成.a库文件的工具
- Scala 编程(一)Scala 编程总览
- POJ 1470 Closest Common Ancestors(LCA 最近公共祖先)
- 五.	Java集合概要
- RMQ问题第一弹
热门文章
- 【bzoj1712】[Usaco2007 China]Summing Sums 加密 矩阵乘法
- OracleHelp以及其简单应用
- react 入门与进阶教程
- [COGS2652]秘术「天文密葬法」
- KNIGHTS - Knights of the Round Table 圆桌骑士 点双 + 二分图判定
- [JSOI2009]计数问题 二维树状数组
- BZOJ1597 &; 洛谷2900:[USACO2008 MAR]Land Acquisition 土地购买——题解
- Mac安装mysqldb
- UVA.10305 Maximum Product (暴力)
- ";HK";日常之冻结术