【树状数组】【dfs】树
樹
題目大意:
有一棵樹,當(dāng)給一個(gè)點(diǎn)加上一個(gè)val時(shí),他的兒子會(huì)減val,而他兒子的兒子會(huì)加上val(-(-val)=val),有m條指令,要不輸出某個(gè)點(diǎn)的值,要不給某個(gè)點(diǎn)加值
原題:
題目描述
小L非常喜歡樹。最近,他發(fā)現(xiàn)了一棵有趣的樹。這棵樹有n個(gè)節(jié)點(diǎn)(1到n編號(hào)),節(jié)點(diǎn)i有一個(gè)初始的權(quán)值ai。這棵樹的根是節(jié)點(diǎn)1。
這棵樹有一個(gè)特殊的性質(zhì):當(dāng)你給節(jié)點(diǎn)i的權(quán)值加 val 的時(shí)候,節(jié)點(diǎn)i的所有兒子的權(quán)值都會(huì)加 -val。注意當(dāng)你給節(jié)點(diǎn)i的兒子的權(quán)值加 -val 時(shí),節(jié)點(diǎn)i的這個(gè)兒子的所有兒子的權(quán)值都會(huì)加 -(-val),以此類推。樣例說明可以很好地幫助你理解這個(gè)性質(zhì)。
有2種操作:
操作(a).“1 x val”表示給節(jié)點(diǎn)x的權(quán)值加val。
操作(b).“2 x”輸出節(jié)點(diǎn)x當(dāng)前的權(quán)值。
為了幫助小L更好地理解這棵樹,你必須處理m個(gè)操作。
輸入
第一行包含2個(gè)整數(shù)n和m。
第二行包含n個(gè)整數(shù)a1,a2,…,an(1≤ai≤1000)。
接下來的n-1行,每行兩個(gè)整數(shù)u和v(1≤u接下來的m行,每行包含2種操作的一種。每個(gè)操作都保證1≤x≤n,1≤val≤1000。
輸出
對(duì)于每個(gè)操作(b),輸出一個(gè)整數(shù),表示節(jié)點(diǎn)x當(dāng)前的權(quán)值。
輸入樣例
5 5 1 2 1 1 2 1 2 1 3 2 4 2 5 1 2 3 1 1 2 2 1 2 2 2 4輸出樣例
3 3 0說明
【輸入輸出樣例說明】
初始各個(gè)節(jié)點(diǎn)的權(quán)值依次為[1,2,1,1,2]。
第一個(gè)操作給節(jié)點(diǎn)2的權(quán)值增加3,會(huì)給節(jié)點(diǎn)2的兒子4、5的權(quán)值增加-3。此時(shí)各個(gè)節(jié)點(diǎn)的權(quán)值變成[1,5,1,-2,-1]。
第二個(gè)操作給節(jié)點(diǎn)1的權(quán)值增加2,會(huì)給節(jié)點(diǎn)1的兒子2、3的權(quán)值增加-2,然后會(huì)給節(jié)點(diǎn)2的兒子4、5的權(quán)值增加-(-2)。各個(gè)節(jié)點(diǎn)的權(quán)值變成[3,3,-1,0,1]。
【數(shù)據(jù)說明】
對(duì)于50%的數(shù)據(jù),1≤n≤2000,1≤m≤2000。
對(duì)于100%的數(shù)據(jù),1≤n≤100000,1≤m≤100000。
解題思路
80分思路1:
當(dāng)給某個(gè)點(diǎn)加值時(shí),dfs下去,要輸出時(shí),直接輸出
#include<cstdio> using namespace std; int n,m,x,y,z,b[100005],head[100005]; struct rec {int to,next; }a[100005]; void dfs(int now,int d) {b[now]+=d;//相加for (int i=head[now];i;i=a[i].next)//子節(jié)點(diǎn)dfs(a[i].to,-d);//數(shù)字翻轉(zhuǎn) } int main() {scanf("%d %d",&n,&m);for (int i=1;i<=n;++i)scanf("%d",&b[i]);for (int i=1;i<n;++i){scanf("%d %d",&x,&y);a[i].to=y;//存儲(chǔ)a[i].next=head[x];head[x]=i;}for (int i=1;i<=m;++i){scanf("%d %d",&y,&x);if (y==2){printf("%d\n",b[x]);//輸出continue;}scanf("%d",&z);//輸入dfs(x,z);//dfs下去} }80分思路2:
給某個(gè)點(diǎn)價(jià)值時(shí),先存下來,等輸出時(shí),再往父節(jié)點(diǎn)搜
#include<cstdio> using namespace std; int n,m,x,y,z,b[100005],dad[100005],zj[100005]; int dfs(int dep,int now) {if (!dep) return 0;//搜完了return zj[dep]*now+dfs(dad[dep],-now);//繼續(xù)往上 } int main() {scanf("%d %d",&n,&m);for (int i=1;i<=n;++i)scanf("%d",&b[i]);for (int i=1;i<n;++i){scanf("%d %d",&x,&y);dad[y]=x;//記錄父節(jié)點(diǎn)}for (int i=1;i<=m;++i){scanf("%d %d",&x,&y);if (x&1)//加值{scanf("%d",&z);zj[y]+=z;//記錄起來continue;}printf("%d\n",b[y]+dfs(y,1));//往父節(jié)點(diǎn)搜} }正解
按奇偶性分下類
然后樹狀數(shù)組修改即可(懶)
總結(jié)
以上是生活随笔為你收集整理的【树状数组】【dfs】树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一键生成广告图片,亚马逊推出“卖家专用”
- 下一篇: 初一模拟赛总结(3.16)