HDU 3966 dfs序+LCA+树状数组
题目意思很明白:
给你一棵有n个节点的树,对树有下列操作:
I c1 c2 k 意思是把从c1节点到c2节点路径上的点权值加上k
D c1 c2 k 意思是把从c1节点到c2节点路径上的点权值减去k
Q a 查询节点a的权值
数据大小 节点个数 n[1,50000], 操作次数 op[0,30000];
不会树链剖分 故只有想其他的方法。
这道题有点类似今年上海网络赛的1003 ,不过那题我没做;
算法思路:
以节点1 为根,求出节点i 的 dfs序列 tim[i][2];
其中tim[i][0]存的是进入节点i的时间 ,tim[i][1]存的是离开节点i的时间
看操作: I a b k, 节点a到b的路径上所有点+k;最朴素的算法首先找到他们的最近公共祖先(LCA)(我用RMQ)写的;然后在路径上的每一个节点都+k;
假设树根是1
从a到树根的每一个节点x都满足tim[x][0]<=tim[a][0]<=tim[x][1];如此 如果引入一个数列nt,如果nt(tim[a][0])+=k,那么 nt数列从tim[x][0]到tim[x][1]项的和就加了k,这就相当于把从a到根节点的每一个节点的权值加上了k;
如果节点x不在a到根的路径上呢?那么只有可能是tim[x][0]>tim[a][0] or tim[x][1]<tim[a][0] 故上面的这种做法对其他的点没有影响
根据这种思路 ,那解法就相对简单了:
加上差分数列的思想
a b的LCA是t,把 a b节点都加上k,然后把t的父节点-2;当然 t节点是加了两遍的 所以需要减去一遍 也就是把t节点-1,父节点当然也要+1了
如果有了dfs序,就可以很清晰的看出来 如果一个节点x在这条路径上 那么tim[x][0]<=one of (tim[a][0],tim[b][0])<=tim[x][1];
附上代码渣渣:
// hdu 3966
#include<iostream>
#include<stdio.h>
#include<string.h>
#include <string>
#include <cmath>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include<stdlib.h>
#include <vector>
using namespace std; #define ll __int64
#define CL(a,b) memset(a,b,sizeof(a))
#define MAX_NODE 50010 int n,m,q; int log_2(int x)
{
return (int)(log((double)x)/log(2.0));
} int tim[MAX_NODE][],ti;
int rmq[MAX_NODE*][],cq,fv[MAX_NODE];
int pre[MAX_NODE];
int value[]; typedef struct myedge
{
int v,next;
}E; E edge[];
int head[],ce; void inithead()
{
CL(head,-);
ce=;
}
void addedge(int s,int e)
{
edge[ce].v=e;edge[ce].next=head[s];head[s]=ce++;
edge[ce].v=s;edge[ce].next=head[e];head[e]=ce++;
} void initrmq()
{
int i,j;
for(j=;(<<j)<=cq;j++)
{
for(i=;i+(<<j)-<=cq;i++)
{
rmq[i][j]=min(rmq[i][j-],rmq[i+(<<(j-))][j-]);
}
}
}
int quermq(int s,int e)
{
int i=log_2(e-s+);
return min(rmq[s][i],rmq[e-(<<i)+][i]);
} ll nt[]; int lowbit(int i)
{
return i&(-i);
} void modify(int i,ll v)
{
if(i==)return ;
for(i;i<=n;i+=lowbit(i))
{
nt[i]+=v;
}
} ll sum(int i)
{
ll rem=;
for(i;i>;i-=lowbit(i))
rem+=nt[i];
return rem;
} int dfs(int i,int pr)
{
ti++;
tim[i][]=ti;
// cout<<i<<" tim "<<ti<<endl;
rmq[++cq][]=tim[i][];
fv[i]=cq;
pre[ti]=pr;
int p=head[i];
while(p!=-)
{
int v=edge[p].v;
if(tim[v][]==)
{
dfs(v,tim[i][]);
rmq[++cq][]=tim[i][];
}
p=edge[p].next;
}
tim[i][]=ti;
return ;
} void inc(int s,int e,int k)
{
int rs=fv[s];
int re=fv[e];
int rt=quermq(min(rs,re),max(rs,re));
re=tim[e][];
rs=tim[s][];
// cout<<rs<<' '<<re<<' '<<rt<<' '<<pre[rt]<<endl;
if(s==e)
{
value[s]+=k;
return ;
}
modify(rs,k);
modify(re,k);
modify(rt,-k);
modify(pre[rt],-k);
} void dec(int s,int e,int k)
{
k=-k;
int rs=fv[s];
int re=fv[e];
int rt=quermq(min(rs,re),max(rs,re));
re=tim[e][];
rs=tim[s][];
if(s==e)
{
value[s]+=k;
return ;
}
modify(rs,k);
modify(re,k);
modify(rt,-k);
modify(pre[rt],-k);
} ll que(int k)
{
int rl=tim[k][];
int rr=tim[k][];
// cout<<rl<<' '<<rr<<endl;
return (ll)value[k]+sum(rr)-sum(rl-);
} char op[]; int main()
{
while(scanf("%d %d %d",&n,&m,&q)!=EOF)
{
CL(nt,);
CL(rmq,);cq=;
CL(fv,);
CL(pre,);
CL(tim,);ti=;
inithead();
int i,j,k;
int a,b,c;
for(i=;i<=n;i++)
{
scanf("%d",value+i);
}
for(i=;i<n;i++)
{
scanf("%d %d",&a,&b);
addedge(a,b);
}
dfs(,);
/*
for(i=1;i<=cq;i++)
{
printf("%d ",rmq[i][0]);
}cout<<endl;
*/
initrmq();
for(i=;i<q;i++)
{
scanf("%s",op);
if(op[]=='I')
{
scanf("%d %d %d",&a,&b,&c);
inc(a,b,c);
}
else if(op[]=='D')
{
scanf("%d %d %d",&a,&b,&c);
dec(a,b,c);
}
else if(op[]=='Q')
{
scanf("%d",&a);
printf("%I64d\n",que(a));
}
} } return ;
}
HDU 3966 dfs序+LCA+树状数组的更多相关文章
- BZOJ 4999: This Problem Is Too Simple! DFS序+LCA+树状数组+离线
Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) , ...
- HDU 6203 ping ping ping(dfs序+LCA+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连 ...
- POJ 2763 Housewife Wind(DFS序+LCA+树状数组)
Housewife Wind Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 11419 Accepted: 3140 D ...
- BZOJ 2819: Nim dfs序维护树状数组,倍增
1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...
- 【BZOJ1103】大都市meg(DFS序,树状数组)
题意:有一颗树,1号点为根,保证编号小的点深度较小,初始状态每条边都没有被标记,要求实现两个操作在线: A:将连接x,y的边标记 W:查询从1到x的路径上有多少条边未被标记 n<=2*10^5 ...
- 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...
- BZOJ 1103: [POI2007]大都市meg(dfs序,树状数组)
本来还想链剖的,结果才发现能直接树状数组的= = 记录遍历到达点与退出点的时间,然后一开始每个到达时间+1,退出时间-1,置为公路就-1,+1,询问直接点1到该点到达时间求和就行了- - CODE: ...
- 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)
题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...
- 【POJ3321】Apple Tree(DFS序,树状数组)
题意:给一棵n个节点的树,每个节点开始有一个苹果,m次操作 1.将某个结点的苹果数异或 1 2.查询一棵子树内的苹果数 n,m<=100000 思路:最近一段时间在思考树上统计问题的算法 发 ...
随机推荐
- div需要重置吗?
看看所有常用标签的默认margin.padding?Demo戳这里 - - 当你每次看到为那一长串标签设置margin: 0; padding: 0; 的时候,你是否想看看哪些标签,在哪些浏览器里有默 ...
- Lua 学习笔记(二)
七.再论lua函数 1.lua中的函数被认为是带有词法定界和第一类值 a.词法定界:被嵌套的函数可以访问外部函数的变量 b.第一类值: lua中的函数可以放在变量中 (函数指针?) ...
- url中的jsessionid解释
(1) 这是一个保险措施 因为Session默认是需要Cookie支持的 但有些客户浏览器是关闭Cookie的 这个时候就需要在URL中指定服务器上的session标识,也就是5F4771183629 ...
- 基数---SQL Server 2008 Bible
关系类型 主要实体的键 次要实体的键 一对一 主要实体-主键-单个元组 主要实体-主键-单个元组 一对多 主要实体-主键-单个元组 次要实体-外键-多个元组 多对多 多个元组 多个元组
- <php>添加数据注意事项
如果报错信息里有:fetch_all(),肯定是sql语句写错 get传值:<a href="chuli.php?name=1&code=2">处理</a ...
- 执行testng appium用例失败,自动截图
新建一个截图监听类ScreenShotListener ,重写onTestFailure方法,里面定义了 监听的driver ,截图文件路径和名称 package com.fsssc.htsgl.ut ...
- javascript对象的理解
从代码中体会javascript中的对象: <!DOCTYPE html> <html> <head> <meta charset="utf-8&q ...
- Css中的变形及过渡动画
在css3的标准中新增加了变形样式,这些样式使得网页中各元素的位置形状的变换变得更加容易.其语法如下: transform:none | <transform-function>+ 其中对 ...
- (转)iOS Wow体验 - 第七章 - 操作图例与触屏人机工学
本文是<iOS Wow Factor:Apps and UX Design Techniques for iPhone and iPad>第七章译文精选,其余章节将陆续放出.上一篇:Wow ...
- 事关Animation Tree的工作随笔(二)
上回说到,游戏项目中客观会遇到逻辑状态的复杂性和动画状态的单一性之间的矛盾,那么Animation Tree是如何解决这个问题的呢? 这又需要引入一个定律:就是逻辑状态无论有多么复杂,但一套逻辑状态组 ...