HAOI2015 樹上操作

2022-05-19 10:10:48 字數 1575 閱讀 9020

題目:bzoj4034、洛谷p3178。

題目大意:有一棵點數為 n 的樹,以點 1 為根,且樹有點權。然後有 m 個操作,分為三種:

操作 1 :把某個節點 x 的點權增加 a 。

操作 2 :把某個節點 x 為根的子樹中所有點的點權都增加 a 。

操作 3 :詢問某個節點 x 到根的路徑中所有點的點權和。

現在要你輸出所有詢問的答案。

解題思路:對樹上的節點修改查詢,很容易想到樹鏈剖分。

單點修改就相當於只包含乙個節點的區間修改。

子樹修改,由於樹鏈剖分中一棵子樹的dfs序連續,相當於區間修改。

查詢就相當於多次區間查詢。

樹鏈剖分時間複雜度$o(n\log^2 n)$。

c++ code:

#include#include#include#define n 100005

#define mem(a) memset(&a,0,sizeof a)

#define ll long long

int n,m,a[n],aa[n],dfn[n],idx,cnt,head[n],sz[n],fa[n],top[n],son[n],dep[n];

ll ans;

struct edgee[n<<1];

struct segmenttreenoded[n<<2];

inline int readint()

void dfs(int now)

}void dfs2(int now)

inline void pushdown(int len,int o)

void build(int l,int r,int o)

int mid=(l+r)>>1;

build(l,mid,o<<1);

build(mid+1,r,o<<1|1);

d[o].s=d[o<<1].s+d[o<<1|1].s;

}void add(int l,int r,int o,int l,int r,int k)

pushdown(r-l+1,o);

int mid=(l+r)>>1;

if(l<=mid)add(l,mid,o<<1,l,r,k);

if(mid>1;

if(l<=mid)query(l,mid,o<<1,l,r);

if(mid}void que(int x)

query(1,n,1,dfn[1],dfn[x]);

}int main();

head[u]=cnt;

e[++cnt]=(edge);

head[v]=cnt;

} fa[1]=top[1]=dep[1]=1;

dfs(1);dfs2(1);

for(int i=1;i<=n;++i)aa[dfn[i]]=a[i];

build(1,n,1);

while(m--)else

if(f==2)else

} return 0;

}

HAOI2015 樹上操作

題目描述 有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數...

HAOI2015 樹上操作

有一棵點數為 n 的樹,以點 1 為根,且樹點有邊權。然後有 m 個操作,分為三種 操作 1 把某個節點 x 的點權增加 a 操作 2 把某個節點 x 為根的子樹中所有點的點權都增加 a 操作 3 詢問某個節點 x 到根的路徑中所有點的點權和。輸入格式 第一行包含兩個整數 n,m 表示點數和運算元。...

HAOI2015 樹上操作

嘟嘟嘟 樹剖自然可解,就是一道板子題,而且這道題還只問到根節點的距離是多少,而不是樹上任意兩點距離,就更方便了。1 include2 include3 include4 include5 include6 include7 include8 include9 include10 include11 ...