题目链接:

  Hdu 3966 Aragorn's Story

题目描述:

  给出一个树,每个节点都有一个权值,有三种操作:

  1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x;

  2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x;

  3:(Q, x) 查询节点x的权值为多少?

解题思路:

  可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std; const int maxn = ;
#define lson(x) 2*x+1
#define rson(x) 2*x+2 struct e
{
int to, next;
}edge[maxn*];
struct node
{
int l, r, val, x;
int Mid ()
{
return (l+r)/;
}
}tree[maxn*];
int val[maxn], x[maxn], deep[maxn], size[maxn], tot, num;
int son[maxn], top[maxn], id[maxn], head[maxn], fa[maxn]; void init ()
{
num = tot =;
memset (head, -, sizeof(head));
} void Add (int from, int to)
{
edge[tot].to = to;
edge[tot].next = head[from];
head[from] = tot ++;
} //找重边
void dfs1 (int u, int f, int dep)
{
son[u] = ;
fa[u] = f;
deep[u] = dep;
size[u] = ; for (int i=head[u]; i!=-; i=edge[i].next)
{
int v = edge[i].to;
if (v == f) continue;
dfs1 (v, u, dep+);
size[u] += size[v];
if (size[son[u]] < size[v])
son[u] = v;
}
} //重边连接成重链
void dfs2 (int u, int tp)
{
top[u] = tp;
id[u] = ++num;
if (son[u]) dfs2 (son[u], tp); for (int i=head[u]; i!=-; i=edge[i].next)
{
int v = edge[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2 (v, v);
}
} //区间更新线段树,向下一层更新
void pushup (int x)
{
tree[lson(x)].x += tree[x].x;
tree[rson(x)].x += tree[x].x;
tree[lson(x)].val += tree[x].x;
tree[rson(x)].val += tree[x].x;
tree[x].x = ;
} void build (int root, int l, int r)
{
tree[root].l = l;
tree[root].r = r;
tree[root].x = tree[root].val = ; if (l == r)
{
tree[root].val = val[l];
return ;
} build (lson(root), l, tree[root].Mid());
build (rson(root), tree[root].Mid()+, r);
} void updata (int root, int l, int r, int x)
{
if (tree[root].l == l && r == tree[root].r)
{
tree[root].val += x;
tree[root].x += x;
return ;
} if (tree[root].x)
pushup (root); if (r <= tree[root].Mid())
updata (lson(root), l, r, x);
else if (tree[root].Mid() < l)
updata (rson(root), l, r, x);
else
{
updata (lson(root), l, tree[root].Mid(), x);
updata (rson(root), tree[root].Mid()+, r, x);
}
} int query (int root, int x)
{
if (tree[root].l == tree[root].r && tree[root].l == x)
return tree[root].val; if (tree[root].x)
pushup (root); if (x <= tree[root].Mid())
query (lson(root), x);
else
query (rson(root), x);
} //处理节点u,v
void alter (int u, int v,int x)
{
int tp1 = top [u];
int tp2 = top [v]; while (tp1 != tp2)
{//两个节点不在同一个重链上
if (deep[tp1] < deep[tp2])
{
swap (tp1, tp2);
swap (u, v);
}//deep深的重链上升 updata (, id[tp1], id[u], x);
u = fa[tp1];
tp1 = top[u];
} //在同一条重链上
if (deep[u] > deep[v])
swap (u, v);
updata (, id[u], id[v], x); } int main ()
{
int n, m, q; while (scanf ("%d %d %d", &n, &m, &q) != EOF)
{
init ();
for (int i=; i<=n; i++)
scanf ("%d", &x[i]);
for (int i=; i<m; i++)
{
int x, y;
scanf ("%d %d", &x, &y);
Add (x, y);
Add (y, x);
} dfs1 (, , );
dfs2 (, ); //hash原来节点
for (int i=; i<=n; i++)
val[id[i]] = x[i];
build (, , n); while (q --)
{
char str[];
int l, r, x;
scanf ("%s", str); if (str[] == 'Q')
{
scanf ("%d", &x);
printf ("%d\n", query (, id[x]));
}
else if (str[] == 'I')
{
scanf ("%d %d %d", &l, &r, &x);
alter (l, r, x);
}
else
{
scanf ("%d %d %d", &l, &r, &x);
alter (l, r, -x);
} }
}
return ;
}

Hdu 3966 Aragorn's Story (树链剖分 + 线段树区间更新)的更多相关文章

  1. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  2. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  5. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  6. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  7. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  8. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  9. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  10. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

随机推荐

  1. 模式识别之聚类算法k-均值---k-均值聚类算法c实现

    //写个简单的先练习一下,测试通过 //k-均值聚类算法C语言版   #include <stdlib.h>      #include <stdio.h>      #inc ...

  2. ASP.NET MVC判断基于Cookie的Session过期

    当我们第一次请求访问时,可以看到Response的Set-Cookie里添加了ASP.NET_SessionId的值,以后再访问时可以看到Resquest里的Cookie已经包含这个Key.   Se ...

  3. 通过反射获取java nio Direct Memory 的最大值和已使用值

    (ps:jdk1.7及之后可通过MBean获取这两个值)

  4. nginx搭建支持http和rtmp协议的流媒体server之中的一个

    实验目的:让Nginx支持flv和mp4格式文件,支持RTMP协议的直播和点播:同一时候打开RTMP的HLS功能 ​资料:HTTP Live Streaming(缩写是 HLS)是一个由苹果公司提出的 ...

  5. 记录001:AS11 BAPI

    未知元素(174657434)  15:05:41AS11有没有BAPI呀?有做过的吗 BAPI_FIXEDASSET_OVRTAKE_CREATE

  6. (linux)platform_driver_probe与platform_driver_register的区别

      [驱动注册]platform_driver_register()与platform_device_register()          设备与驱动的两种绑定方式:在设备注册时进行绑定及在驱动注册 ...

  7. 织梦DedeCMS信息发布员发布文章默认自动审核更新并生成HTML页面

    织梦DedeCMS信息发布员发布文章默认自动审核更新并生成HTML页面 一直以为DEDECMS的信息发布员在后台发布文章后,非要管理员审核才能显示,今天一哥们问我这个问题.问:“能不能直接发布,并自动 ...

  8. stringBuffer、StringBuilder、排序、Arrays、Jdk1.5新特性(java基础知识十三)

    1.StringBuffer类的概述 * A:StringBuffer类概述 * 通过JDK提供的API,查看StringBuffer类的说明 * 1.线程安全的可变字符序列. * 2.可将字符串缓冲 ...

  9. 根据用户时区显示当地时间 javascript+php

    在跨时区应用中会用到下面代码,这是以前写的一段代码. 服务器保存相关时间配置,保存形式为GMT时间,客户端需要根据客户所在时区做相应显示,以符合客户习惯. ​1. [代码][JavaScript]代码 ...

  10. re(正则表达式)模块

    一.最常用的匹配语法 re.match 从头开始匹配 re.search 匹配包含 re.findall 把所有匹配到的字符放到以列表中的元素返回 re.split  以匹配到的字符当做列表分隔符 r ...