LightOJ 1348 Aladdin and the Return Journey (树链剖分)

树链剖分模板题。

最近一直有比赛。。好长时间没写了。明显生疏了。。找个模板题熟悉一下。

代码如下:

#include <iostream>
#include <string.h>
#include <math.h>
#include <queue>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <set>
#include <stdio.h>
using namespace std;
#define LL __int64
#define pi acos(-1.0)
#define root 1, n, 1
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
//#pragma comment(linker, "/STACK:1024000000")
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const double eqs=1e-3;
const int MAXN=30000+10;
int head[MAXN], cnt, tot, n;
int siz[MAXN], dep[MAXN], w[MAXN], top[MAXN], fa[MAXN], son[MAXN];
int sum[MAXN<<2];
int a[MAXN];
struct node
{
        int u, v, next;
}edge[MAXN<<1];
void add(int u, int v)
{
        edge[cnt].u=u;
        edge[cnt].v=v;
        edge[cnt].next=head[u];
        head[u]=cnt++;
}
void init()
{
        memset(head,-1,sizeof(head));
        cnt=tot=0;
        memset(sum,0,sizeof(sum));
        memset(son,0,sizeof(son));
        memset(dep,0,sizeof(dep));
}
void dfs1(int u, int p)
{
        siz[u]=1;
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v==p) continue ;
                fa[v]=u;
                dep[v]=dep[u]+1;
                dfs1(v,u);
                siz[u]+=siz[v];
                if(siz[v]>siz[son[u]]) son[u]=v;
        }
}
void dfs2(int u, int tp)
{
        w[u]=++tot;top[u]=tp;
        if(son[u]) dfs2(son[u],tp);
        for(int i=head[u];i!=-1;i=edge[i].next){
                int v=edge[i].v;
                if(v!=fa[u]&&v!=son[u])
                        dfs2(v,v);
        }
}
struct Line_Tree
{
        void PushUp(int rt)
        {
                sum[rt]=sum[rt<<1]+sum[rt<<1|1];
        }
        void Update(int p, int x, int l, int r, int rt)
        {
                if(l==r){
                        sum[rt]=x;
                        return ;
                }
                int mid=l+r>>1;
                if(p<=mid) Update(p,x,lson);
                else Update(p,x,rson);
                PushUp(rt);
        }
        int Query(int ll, int rr, int l, int r, int rt)
        {
                if(ll<=l&&rr>=r){
                        return sum[rt];
                }
                int mid=l+r>>1, ans=0;
                if(ll<=mid) ans+=Query(ll,rr,lson);
                if(rr>mid) ans+=Query(ll,rr,rson);
                return ans;
        }
}lt;
int SumQuery(int u, int v)
{
        int f1=top[u], f2=top[v], ans=0;
        while(f1!=f2){
                if(dep[f1]<dep[f2]){
                        swap(u,v);
                        swap(f1,f2);
                }
                ans+=lt.Query(w[f1],w[u],root);
                u=fa[f1];f1=top[u];
        }
        if(dep[u]<dep[v]){
                swap(u,v);
        }
        return ans+lt.Query(w[v],w[u],root);
}
int main()
{
        int t, u, v, q, i, x, Case=0;
        scanf("%d",&t);
        while(t--){
                scanf("%d",&n);
                for(i=1;i<=n;i++){
                        scanf("%d",&a[i]);
                }
                init();
                for(i=1;i<n;i++){
                        scanf("%d%d",&u,&v);
                        u++;v++;
                        add(u,v);
                        add(v,u);
                }
                dfs1(1,-1);
                dfs2(1,1);
                for(i=1;i<=n;i++){
                        lt.Update(w[i],a[i],root);
                }
                scanf("%d",&q);
                printf("Case %d:\n",++Case);
                while(q--){
                        scanf("%d",&x);
                        if(!x){
                                scanf("%d%d",&u,&v);
                                u++;v++;
                                printf("%d\n",SumQuery(u,v));
                        }
                        else{
                                scanf("%d%d",&u,&v);
                                u++;
                                lt.Update(w[u],v,root);
                        }
                }
        }
        return 0;
}
时间: 2024-11-06 03:39:21

LightOJ 1348 Aladdin and the Return Journey (树链剖分)的相关文章

Lightoj 1348 Aladdin and the Return Journey (树链剖分)(线段树单点修改区间求和)

Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reac

Light 1348 - Aladdin and the Return Journey(树链剖分)

Light 1348 - Aladdin and the Return Journey 题目链接 树链剖分基础题,注意一个坑点,就是下标按0开始的话按我的写法是会错的,因为son初值赋成0了,要么改一下son初值,要么把下标都+1 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N =

LightOJ 1348 Aladdin and the Return Journey

题意: 给出N个节点的一棵树,每个节点有一个权值. 有两种操作: 1)      0 i j, 问节点i->节点j的路上的总权值. 2)      1 i v, 把节点i的权值改变成v. 思路: 权值在点上的树链剖分+线段树单点更新+线段树成段询问 1 #include <iostream> 2 #include <cstring> 3 #include <string> 4 #include <cstdio> 5 #include <vecto

light1348Aladdin and the Return Journey树链剖分

点更新模版题,线段树 建树的时候没写更新,交了几十次吧. #include<iostream> #include<cstdio> #include<cstring> #include<map> #include<vector> #include<stdlib.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1

树链剖分2——边权改点权

实验对象——2013 noip day1 T3 本来可以直接用倍增lca解决..但是我比较的扯淡..所以用树链剖分来搞 和普通点权不同的是,对于一颗树来说,每一个点的点权被定义为他的父亲到他的边权,所以与一般的树链剖分相比,最后统一到一条链上时,线段树维护的一边端点要加1..其他的就没了.然后注意往上跳的时候的比较时dep[un[a]] 和 dep[un[b]] 不是dep[a] dep[b]; #include <iostream> #include <cstdio> #incl

树链剖分 [HDU 3966] Aragorn&#39;s Story

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3544    Accepted Submission(s): 995 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord

树链剖分入门-Hdu3966 Aragorn&#39;s Story

AC通道:http://acm.hdu.edu.cn/showproblem.php?pid=3966 [题目大意] 一棵树上每个点有权值,每次支持三种操作:给[a,b]路径上的所有节点的权值加上k,给[a,b]路径上的所有节点的权值减去k,以及询问a的权值. [分析] 这是一道树链剖分模板题. 树链剖分,就是将树化成了许多链,将这些链用数据结构保存起来,再去维护这个数据结构. 假设给的树就是一条链,这道题当然很好办:直接将链用线段树存了,因为[a,b]的路径在线段树上也是连续的一段,那么修改一

[GDOI2016] 疯狂动物园 [树链剖分+可持久化线段树]

题面 太长了,而且解释的不清楚,我来给个简化版的题意: 给定一棵$n$个点的数,每个点有点权,你需要实现以下$m$个操作 操作1,把$x$到$y$的路径上的所有点的权值都加上$delta$,并且更新一个版本 操作2,对于有向路径$(x,y)$上的点$a_i$,求下面的和值: $\sum_{i=1}^{len} a_i \sum_{j=1}^{len-i} j$ 操作3,回到第$i$个版本(但是下一次更新以后还是到总版本号+1的那个版本) 思路 这个题显然一眼就是树剖+可持久化数据结构啊 那么核心

树链剖分 [模板]最近公共祖先LCA

本人水平有限,题解不到为处,请多多谅解 本蒟蒻谢谢大家观看 题目:传送门 树链剖分:跑两遍dfs,第一遍找重边,第二遍找重链. 重儿子:父亲节点的所有儿子中子树结点数目最多(size最大)的结点: 轻儿子:父亲节点中除了重儿子以外的儿子: 重边:父亲结点和重儿子连成的边: 轻边:父亲节点和轻儿子连成的边: 重链:由多条重边连接而成的路径: 轻链:由多条轻边连接而成的路径 son[]表示重儿子,top[]表示重链所在的第一个节点,sz[]表示子节点数,fa[]表示父亲节点 图示: code: #i