/*查找更新等操作  用新编号ne 变为有序的,再用线段树 
ne[] 存的是dfs序编号  保证每个重链和子树都是编号连续的 
有序区间才能用线段树 。所以l,r这些都是新编号,输入里的是旧编号*/
//找了半天读不全的错误 
        移位一定要加括号!!!!
        i<<1|1=3
        (i<<1)+1=3
        i<<1+1=4   
      que的返回值是val 所以是ll 
//mid和m别写混了。因为m一般定义为总量,所以以后中间都用mid!!!
//由于函数的参数比较多,调用函数的次数也比较多,所以参数的顺序尽量有规律

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e4+5;
int m,n,p,size[maxn],deep[maxn],f[maxn],son[maxn];
int cnt,head[maxn],nid[maxn],oid[maxn],ncnt,top[maxn];
ll a[maxn];
struct stree{ll value,lazy;
}t[maxn<<2];//线段树范围是4倍
struct ss{int to,nex;}g[maxn<<1];//g是结构体 没法memset
void create(int u,int v){g[++cnt]={v,head[u]};   head[u]=cnt;
}
//往下走 找重链和重儿子son[]
void dfs1(int x,int fath){size[x]=1;deep[x]=deep[fath]+1;son[x]=0;f[x]=fath;for(int i=head[x];i;i=g[i].nex){int v=g[i].to;if(v==fath) continue;//不能往上走dfs1(v,x);size[x]+=size[v];//更新以x为根的树的大小if(size[v]>size[son[x]]) son[x]=v;}
}
void dfs2(int x,int topx){top[x]=topx;//注意 topx不要定义成全局 递归调用时会乱 nid[x]=++ncnt;oid[ncnt]=x;//因为neid初始化为0,要从1开始 所以++得在前 //有重儿子的话,先遍历重链,赋值nid,oidif(son[x]) dfs2(son[x],topx);//再遍历轻链for(int i=head[x];i;i=g[i].nex){int v=g[i].to;if(v!=f[x]&&v!=son[x]){dfs2(v,v);}}
}void build(int l=1,int r=n,int rt=1){//建线段树 t[rt].lazy=0;//建树时给每个点lazy赋初值,所以lazy在外面 。若在l==r时执行 只有叶节点 if(l==r){t[rt].value=a[oid[l]];//因为a[]下标存的是旧id return;}int mid=(l+r)>>1;build(l,mid,rt<<1); build(mid+1,r,rt<<1|1);t[rt].value=t[rt<<1].value+t[rt<<1|1].value;//构造都要pushup
}
//lazy value更新都是   加上(减去)用+= 。变为 用=
void pushdown(int ln,int rn,int rt){if(t[rt].lazy){t[rt<<1].value+=t[rt].lazy*ln;t[rt<<1|1].value+=t[rt].lazy*rn;t[rt<<1].lazy+=t[rt].lazy;t[rt<<1|1].lazy+=t[rt].lazy;}t[rt].lazy=0;
}
void update(ll k,int L,int R,int l=1,int r=n,int rt=1){if(L>r||R<l) return ;if(L<=l&&r<=R){t[rt].value+=k*(r-l+1);t[rt].lazy+=k;  return ;}int mid=(l+r)>>1;  pushdown(mid-l+1,r-mid,rt);update(k,L,R,l,mid,rt<<1);update(k,L,R,mid+1,r,rt<<1|1);//该题是单点查询,所以不用pushup求和
}
ll que(int k,int l=1,int r=n,int rt=1){if(k<l||k>r) return 0;//超出范围回0,所以后面可以直接返回左右相加 if(l==r) return t[rt].value;int mid=(l+r)>>1;pushdown(mid-l+1,r-mid,rt);//有lazy所以mid后面都要pushdown 才能保证value是正确的 return que(k,l,mid,rt<<1)+que(k,mid+1,r,rt<<1|1);
}
void change(int x,int y,ll k){while(top[x]!=top[y]){  if(deep[top[x]]<deep[top[y]]) swap(x,y); update(k,nid[top[x]],nid[x]); //更新深度大的那条链,更新完了再向上跳 //topx和x是旧编码,要用线段树得用新编码,所以得用nidx=f[top[x]];}
//前面是while所以一直跳到top相等 即xy在同一重链上(dfs序连续可转为线段树)再更新x到y区间if(deep[x]>deep[y]) swap(x,y);; update(k,nid[x],nid[y]);
}
//change:找到最近公共祖先 并分段update int main(){int x,y;ll k; while(~scanf("%d%d%d",&n,&m,&p)){ cnt=ncnt=0;for(int i=1;i<=n;i++){head[i]=0; scanf("%lld",&a[i]);}for(int i=1;i<=m;i++){scanf("%d%d",&x,&y);create(x,y);create(y,x);}dfs1(1,0);dfs2(1,1); build();for(int i=1;i<=p;i++){char ch[10];scanf("%s",ch);//%s遇空格结束 if(ch[0]=='Q') {scanf("%d",&x);printf("%lld\n",que(nid[x]));} else{scanf("%d%d%lld",&x,&y,&k);if(ch[0]=='I') change(x,y,k);else change(x,y,-k);}}}return 0;
} 

hdu3966树链剖分 分析相关推荐

  1. HDU3966(树链剖分)

    题目:Aragorn's Story 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上的所有点权值加上K D C1 C2 K:把C1与C2的路径上的所有 ...

  2. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  3. [hdu3966 Aragorn's Story]树链剖分

    题意:要求在一棵N(<=50000)个带权节点的树上支持3种操作 (1)I u v w,u到v的路径上每个节点权值增加w (2)D u v w,u到v的路径上每个节点权值减少w (3)Q u,求 ...

  4. SPOJ375(树链剖分)

    题目:Query on a tree 题意:给定一棵树,告诉了每条边的权值,然后给出两种操作: (1)把第i条边的权值改为val (2)询问a,b路径上权值最大的边 分析:本题与HDU3966差不多, ...

  5. AcWing 397. 逃不掉的路(边双连通分量缩点成树 + 树链剖分乱搞)

    整理的算法模板合集: ACM模板 我们知道在同一个边双连通分量中的点没有必经边(因为至少有两条分离的路径). 所以我们直接tarjan求出桥后缩点,然后求一下树上两点间的距离即可. 那么如何求树上两点 ...

  6. [SPOJ375]QTREE - Query on a tree【树链剖分】

    题目描述 给你一棵树,两种操作. 修改边权,查找边权的最大值. 分析 我们都知道,树链剖分能够维护点权. 而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上. 注意,lca的 ...

  7. HDU - 3966 Aragorn's Story(树链剖分)

    题目传送门:HDU - 3966 Aragorn's Story 题目大意: 存在一个树,树上每个节点为一个阵营,阵营中存在敌人,现在要进行以下操作 I  C1  C2  K :将阵营C1到阵营C2路 ...

  8. spoj 375 Query on a tree (树链剖分)

    题目链接: http://www.spoj.com/problems/QTREE/ 题意: 给一颗树,每条边有一个权值.有两种操作: 1.修改某条边的值: 2.询问a.b两点路径上边权的最大值. 分析 ...

  9. SPOJ- QTREE+HDU 3966(树链剖分裸题

    题目:维护一个树,支持修改边长,查询任意两点间距离. 思路:学习了一下树链剖分,还是看了一阵子才看懂的(大概两个多小时orz...)其实总的来说并不是很难,主要是数组比较多,然后看的那篇博客大概是为了 ...

  10. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

最新文章

  1. MySQL索引的学习和研究
  2. Linux内核源码结构
  3. 【Linux】Linux中目录结构说明
  4. Socket之TCP客户端【Python】
  5. 亲儿子 | Azure SignalR 服务现在支持 ASP.NET
  6. 高速pcb设计指南 1~8
  7. Windows下安装和配置Maven的方法及注意事项
  8. linux的文件权限前面的东西,linux 文件权限解析
  9. Visual studio 2012 创建web service
  10. 计算机二级题库office基础知识,计算机二级office题库
  11. P10(1R)单红V706模组32X16 LED显示屏的二十项小实验
  12. 微信小程序获取手机号用户拒接之后再掉接口微信返回40163
  13. Excel如何合并相同项单元格
  14. 二进制安装PLG日志服务
  15. 淘宝商品详情页API接口|tb获取商品主图接口
  16. 各种水果使用套袋的材料选择
  17. lesson2--html-css基础主要知识点
  18. [附源码]Java计算机毕业设计SSM电子工厂进销存管理系统
  19. wireshark图形界面介绍
  20. 靶机渗透练习19-Hacker kid

热门文章

  1. web邮箱和客户端的区别
  2. NR 5G SSB介绍
  3. HZHOST实现自定义FSO权限的方法及其应用
  4. 程序员在大城市奋斗的理由,仅为追求那些不曾见过的五光十色
  5. Working with Qt maya2011
  6. 软件开发合同纠纷的律师随笔
  7. 小目标检测--SNIP
  8. 用matlab进行多项式通分,Matlab控制系统仿真基础
  9. 2023北京国际老年产业博览会/养老产业展/养老服务业展
  10. Spark未授权访问getshell