题目意思很明白:

给你一棵有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+树状数组的更多相关文章

  1. BZOJ 4999: This Problem Is Too Simple! DFS序+LCA+树状数组+离线

    Code: #include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) , ...

  2. HDU 6203 ping ping ping(dfs序+LCA+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意: n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V 无法连 ...

  3. POJ 2763 Housewife Wind(DFS序+LCA+树状数组)

    Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 11419   Accepted: 3140 D ...

  4. BZOJ 2819: Nim dfs序维护树状数组,倍增

    1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家.2.把堆v中的石子数变为k. 分析: ...

  5. 【BZOJ1103】大都市meg(DFS序,树状数组)

    题意:有一颗树,1号点为根,保证编号小的点深度较小,初始状态每条边都没有被标记,要求实现两个操作在线: A:将连接x,y的边标记 W:查询从1到x的路径上有多少条边未被标记 n<=2*10^5 ...

  6. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

  7. BZOJ 1103: [POI2007]大都市meg(dfs序,树状数组)

    本来还想链剖的,结果才发现能直接树状数组的= = 记录遍历到达点与退出点的时间,然后一开始每个到达时间+1,退出时间-1,置为公路就-1,+1,询问直接点1到该点到达时间求和就行了- - CODE: ...

  8. 【Tyvj2133&BZOJ1146】网络管理Network(树套树,DFS序,树状数组,主席树,树上差分)

    题意:有一棵N个点的树,每个点有一个点权a[i],要求在线实现以下操作: 1:将X号点的点权修改为Y 2:查询X到Y的路径上第K大的点权 n,q<=80000 a[i]<=10^8 思路: ...

  9. 【POJ3321】Apple Tree(DFS序,树状数组)

    题意:给一棵n个节点的树,每个节点开始有一个苹果,m次操作 1.将某个结点的苹果数异或 1 2.查询一棵子树内的苹果数 n,m<=100000   思路:最近一段时间在思考树上统计问题的算法 发 ...

随机推荐

  1. Linux 编译安装httpsqs

    wget http://httpsqs.googlecode.com/files/libevent-2.0.12-stable.tar.gz tar zxvf libevent-2.0.12-stab ...

  2. IP地址的存储和使用

    ip地址使用int类型存储,用INET_NTOA()和INET_ATON()转换 mysql'),inet_aton('127.0.0.1'); +-------------------------+ ...

  3. 近期Responsive web design项目经验分享

    关于meta   <meta name="viewport" content="initial-scale=1.0, minimum-scale=1.0, user ...

  4. JavaScript加密解密压缩工具

    <script> a=62; function encode() { var code = document.getElementById('code').value; code = co ...

  5. isArray

    判断一个玩意是不是数组: (1)新方法:Array.isArray(); (2)旧方法:toString(); <!doctype html> <html lang="en ...

  6. 网站卡死,照惯例运行.bat批量处理文件进行重启不起作用

    网站卡死,照惯例运行.bat批量处理文件进行重启不起作用,进入虚拟机控制台进行虚拟机重启仍然不起作用,通过ping分析物理服务器能ping通,各个虚拟机之前也能ping通,但是不能ping通外部,分析 ...

  7. docker 1.10.3 里php出现 curl 56错误码问题解决

    http://www.cnblogs.com/fengwei/p/5899018.html

  8. Android String 转 MD5

    /** * 将字符串转成16 位MD5值 *  * @param string * @return */ public static String MD5(String string) { byte[ ...

  9. 在OCX初始化时获取其在网页中的DOM对象

    OCX初始化的时候会调用SetClientSite,会传入IOleClientSite对象. CComQIPtr<IOleControlSite, &IID_IOleControlSit ...

  10. 【hihoCoder第十四周】无间道之并查集

    就是基础的并查集.0代表合并操作,1代表查询操作.一开始以为会卡路径压缩,忐忑的交了一版裸并查集,结果AC了.数据还是很水的. 以后坚持做hiho,当额外的练习啦~ #include <bits ...