HDU 3966 Aragorn's Story(模板题)【树链剖分】+【线段树】
<题目链接>
题目大意:
给定一颗带点权的树,进行两种操作,一是给定树上一段路径,对其上每个点的点权增加或者减少一个数,二是对某个编号点的点权进行查询。
解题分析:
树链剖分的模板题,还不会树链剖分可以看这里 >>>
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #define Lson l,mid,rt<<1
- #define Rson mid+1,r,rt<<1|1
- using namespace std;
- const int M = 5e4+;
- int head[M],sz[M],son[M],f[M],tid[M],rnk[M],dep[M],top[M];
- int tot,cnt,n,m,q,a[M],pos,ans;
- //sz[]数组,用来保存以x为根的子树节点个数
- //top[]数组,用来保存当前节点的所在链的链首
- //son[]数组,用来保存重儿子
- //dep[]数组,用来保存当前节点的深度
- //f[]数组,用来保存当前节点的父亲
- //tid[]数组,用来保存树中每个节点剖分后的新编号
- //rnk[]数组,线段树中编号对应的原节点编号
- struct edge{
- int v,next;
- }e[M<<];
- struct tree
- {
- int sum,lazy,l,r;
- }tree[M<<];
- void init(){
- tot=cnt=;
- memset(head,-,sizeof(head));
- }
- void add(int u,int v){
- e[++cnt].v=v;e[cnt].next=head[u];
- head[u]=cnt;
- }
- void dfs1(int u,int fa,int d){
- sz[u]=,son[u]=-,f[u]=fa,dep[u]=d;
- for(int i=head[u];~i;i=e[i].next){
- int v=e[i].v;
- if(v==fa) continue;
- dfs1(v,u,d+); //继续向下递归
- sz[u]+=sz[v];
- if(son[u]==-||sz[v]>sz[son[u]]) son[u]=v; //找到该节点的重儿子
- }
- return ;
- }
- void dfs2(int u,int t){
- tid[u]=++tot; //id记录该节点重新编号后的序号
- rnk[tot]=u; //线段树中编号对应的原节点编号
- top[u]=t; //记录下该节点所在重链的链首
- if(son[u]==-) return;
- dfs2(son[u],t); //将重边连成重链
- for(int i=head[u];~i;i=e[i].next){
- int v=e[i].v;
- if(v==f[u]||v==son[u]) continue;
- dfs2(v,v); //找出以轻儿子为链首的重链
- }
- return;
- }
- void Pushup(int rt){
- tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
- }
- void Pushdown(int rt){
- if(tree[rt].lazy){
- int v=tree[rt].lazy;
- tree[rt].lazy=;
- tree[rt<<].lazy+=v;
- tree[rt<<|].lazy+=v;
- tree[rt<<].sum+=v*(tree[rt<<].r-tree[rt<<].l+);
- tree[rt<<|].sum+=v*(tree[rt<<|].r-tree[rt<<|].l+);
- }
- }
- void build(int l,int r,int rt){
- tree[rt].l=l;tree[rt].r=r;tree[rt].lazy=;
- if(l==r){
- tree[rt].sum=a[rnk[l]];
- return;
- }
- int mid=(l+r)>>;
- build(Lson);
- build(Rson);
- Pushup(rt);
- }
- void update(int L,int R,int l,int r,int rt,int v){
- if(L<=l&&r<=R){
- tree[rt].lazy+=v;
- tree[rt].sum+=v*(r-l+);
- return ;
- }
- Pushdown(rt);
- int mid=(l+r)>>;
- if(L<=mid) update(L,R,Lson,v);
- if(R>mid) update(L,R,Rson,v);
- Pushup(rt);
- }
- void query(int l,int r,int rt){
- if(l==r){
- ans=tree[rt].sum;
- return ;
- }
- Pushdown(rt);
- int mid=(l+r)>>;
- if(pos<=mid) query(Lson);
- if(pos>mid) query(Rson);
- return;
- }
- void updates(int x,int y,int v){
- int fx=top[x],fy=top[y]; //x,y所在重链的链首
- while(fx!=fy){//如果这两个点不在一条重链上则一直向上跳,并且不断更新
- if(dep[fx]>dep[fy]){ //fx节点深度更深
- update(tid[fx],tid[x],,n,,v); //更新这一连续区间时,要用该节点在线段树中的编号
- x=f[fx],fx=top[x]; //从这条重链爬到父节点所在重链的链首上去
- }
- else{ //同理
- update(tid[fy],tid[y],,n,,v);
- y=f[fy],fy=top[y];
- }
- }
- if(dep[x]<dep[y]) //在一条重链中时,直接在线段树中将这一段连续的区间更新
- update(tid[x],tid[y],,n,,v);
- else
- update(tid[y],tid[x],,n,,v);
- }
- int main(){
- while(~scanf("%d%d%d",&n,&m,&q)){
- init();
- for(int i=;i<=n;i++) scanf("%d",&a[i]);
- for(int i=;i<=m;i++){
- int u,v;
- scanf("%d%d",&u,&v);
- add(u,v);add(v,u); //链式前向星存下该无向图
- }
- dfs1(,-,);
- dfs2(,);
- build(,n,);
- while(q--){
- char c[];
- int c1,c2,k;
- scanf("%s",c);
- if(c[]=='I'||c[]=='D'){
- scanf("%d%d%d",&c1,&c2,&k);
- if(c[]=='D') k*=-;
- updates(c1,c2,k);
- }
- else{
- scanf("%d",&c1);
- pos=tid[c1]; //pos为c1在线段树中的编号
- query(,n,);
- printf("%d\n",ans);
- }
- }
- }
- return ;
- }
2018-09-09
HDU 3966 Aragorn's Story(模板题)【树链剖分】+【线段树】的更多相关文章
- Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组
Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...
- HDU 2460 Network(双连通+树链剖分+线段树)
HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...
- [luogu3676] 小清新数据结构题 [树链剖分+线段树]
题面 传送门 思路 本来以为这道题可以LCT维护子树信息直接做的,后来发现这样会因为splay形态改变影响子树权值平方和,是splay本身的局限性导致的 所以只能另辟蹊径 首先,我们考虑询问点都在1的 ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- B20J_2836_魔法树_树链剖分+线段树
B20J_2836_魔法树_树链剖分+线段树 题意: 果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u].初始时,这个果树的每个节点上都没有果子(即0个果子). Add u v d ...
- 【bzoj1782】[Usaco2010 Feb]slowdown 慢慢游 树链剖分+线段树
题目描述 每天Farmer John的N头奶牛(1 <= N <= 100000,编号1…N)从粮仓走向他的自己的牧场.牧场构成了一棵树,粮仓在1号牧场.恰好有N-1条道路直接连接着牧场, ...
- 【bzoj1036】树的统计[ZJOI2008]树链剖分+线段树
题目传送门:1036: [ZJOI2008]树的统计Count 这道题是我第一次打树剖的板子,虽然代码有点长,但是“打起来很爽”,而且整道题只花了不到1.5h+,还是一遍过样例!一次提交AC!(难道前 ...
- POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...
- bzoj4034 (树链剖分+线段树)
Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...
- HDU4897 (树链剖分+线段树)
Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...
随机推荐
- Confluence 6 用户宏示例 - Formatted Panel
下面的用演示了如果还写一个用户宏,并在这个宏中创建一个格式化的面板,并且指定颜色.将会创建下面的面板: (Title) 注意:这个面板的标题为空,如果你没有给这个面板标题参数的话. Macro n ...
- vue element-UI 升级报错Cannot find module "element-ui/lib/theme-default/index.css"
饿了么 用之前的版本 有些组件跟api 不一样了所以更新了最新的版本,发现 报一堆错误 主要错误是这个 Cannot find module "element-ui/lib/theme-de ...
- MYSQL查询系列 常考问题
表结构: `student`('id'.'name'.'code'.'age'.'sex')学生表 `teacher`('id'.'name')教师表 `course`('id'.'name'.'te ...
- Memcached简介及环境安装
Memcached简介及环境安装 author:SimpleWu 简介 Memcached是一个自由开源的,高性能,分布式内存对象缓存系统. Memcached是以LiveJournal旗下Danga ...
- ES6笔记
/** * Created by Administrator on 2017/4/13. */ /*---------------------Es6编码规范---------------------* ...
- LeetCode(3):无重复字符的最大子串
本内容是LeetCode第三道题目:无重复字符的最大子串 # -*- coding: utf-8 -*- """ Created on Sun Mar 10 20:14: ...
- django----利用Form 实现两次密码输入是否一样 ( 局部钩子和全局钩子 )
from django import forms # 导入表单模块 from django.core.exceptions import ValidationError class RegisterF ...
- Java基础之多线程框架
一.进程与线程的区别 1.定义: 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比 ...
- javascript 将毫秒值转换为天-小时-分钟-秒钟
var start_timeMS = new Date(start_date).getTime(); var end_timeMS = new Date(end_date).getTime(); va ...
- youtube-dl更新出错解决办法
youtube-dl更新命令: youtube-dl -U 更新报错:无法识别当前版本 ERROR: can't find the current version. Please try again ...