[树链剖分]JZOJ 2677 树A

微笑、不失礼 提交于 2020-01-26 06:21:56

Description

 


已知无向连通图GN个点,N-1条边组成。每个点有给定权值。现有M个操作,操作分为2种:操作1,将某点权值更改;操作2,询问从点A至点B路径上所有点的权值和。

 

Input

 


每个输入文件中仅包含一个测试数据。


第一行包含两个整数N,M


第二行至第N行每行包含2个整数,AB,表示节点A与节点B有一条边相连。


N+1行包含N个整数,表示第N个点的初始权值。


N+2行至第N+M+1行每行包含三个整数,KAB(若K=1,表示将点A权值改为B;若K=2表示询问点A至点B路径上所有点的权值和)




Output

 


输出文件若干行,分别对应每次操作2的答案。

 

Sample Input

3 2
1 2 
1 3 
1 2 3
2 1 3
2 2 3

Sample Output

4
6
 

Data Constraint

 
 

Hint

 


对于60%的数据,1<=N,M<=1000


对于100%的数据,2<=N<=30000;0<=M<=200000

分析

树剖模板……

 

#include <iostream>
#include <cstdio>
#define lson (x<<1)
#define rson ((x<<1)+1)
using namespace std;
const int N=3e4+10;
struct Graph {
    int v,nx;
}g[2*N];
int cnt,list[N];
int top[N],sz[N],seg[N],f[N],dep[N],son[N],w[N];
int t[4*N],scnt,rev[N],rt=1;
int n,m;

void Add(int u,int v) {
    g[++cnt]=(Graph){v,list[u]};list[u]=cnt;
    g[++cnt]=(Graph){u,list[v]};list[v]=cnt;
}

void DFS(int u,int fa) {
    dep[u]=dep[fa]+1;f[u]=fa;sz[u]=1;
    for (int i=list[u];i;i=g[i].nx)
        if (g[i].v!=fa) {
            DFS(g[i].v,u);
            sz[u]+=sz[g[i].v];
            if (sz[g[i].v]>sz[son[u]]) son[u]=g[i].v;
        }
}

void DFS(int u) {
    int s=son[u];
    if (s) {
        top[s]=top[u];
        rev[seg[s]=++scnt]=s;
        DFS(s);
    }
    for (int i=list[u];i;i=g[i].nx)
        if (!top[g[i].v]) top[g[i].v]=g[i].v,rev[seg[g[i].v]=++scnt]=g[i].v,DFS(g[i].v);
}

void Update(int x) {t[x]=t[lson]+t[rson];}

void Build(int x,int l,int r) {
    if (l==r) {
        t[x]=w[rev[l]];
        return;
    }
    int mid=l+r>>1;
    Build(lson,l,mid);Build(rson,mid+1,r);
    Update(x);
}

void Change(int x,int l,int r,int k,int z) {
    if (k<l||r<k) return;
    if (l==r&&l==k) {
        t[x]=z;
        return;
    }
    int mid=l+r>>1;
    if (k<=mid) Change(lson,l,mid,k,z);
    else Change(rson,mid+1,r,k,z);
    Update(x);
}

int Query(int x,int l,int r,int ll,int rr) {
    if (r<l||rr<l||r<ll) return 0;
    if (ll<=l&&r<=rr) return t[x];
    int mid=l+r>>1,ans=0;
    if (ll<=mid) ans+=Query(lson,l,mid,ll,rr);
    if (mid<rr) ans+=Query(rson,mid+1,r,ll,rr);
    return ans;
}

int Query(int x,int y) {
    int fx=top[x],fy=top[y],ans=0;
    while (fx!=fy) {
        if (dep[fx]<dep[fy]) swap(x,y),swap(fx,fy);
        ans+=Query(rt,1,scnt,seg[fx],seg[x]);
        x=f[fx];fx=top[x];
    }
    if (dep[x]<dep[y]) swap(x,y),swap(fx,fy);
    return ans+Query(rt,1,scnt,seg[y],seg[x]);
}

int main() {
    scanf("%d%d",&n,&m);
    for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v);
    for (int i=1;i<=n;i++) scanf("%d",&w[i]);
    DFS(1,0);top[1]=1;rev[seg[1]=++scnt]=1;DFS(1);Build(rt,1,scnt);
    for (;m;m--) {
        int k,a,b;
        scanf("%d%d%d",&k,&a,&b);
        if (k==1) Change(rt,1,scnt,seg[a],b);
        else printf("%d\n",Query(a,b));
    }
}
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!