【树状数组】【dfs】树
樹
題目大意:
有一棵樹,當給一個點加上一個val時,他的兒子會減val,而他兒子的兒子會加上val(-(-val)=val),有m條指令,要不輸出某個點的值,要不給某個點加值
原題:
題目描述
小L非常喜歡樹。最近,他發現了一棵有趣的樹。這棵樹有n個節點(1到n編號),節點i有一個初始的權值ai。這棵樹的根是節點1。
這棵樹有一個特殊的性質:當你給節點i的權值加 val 的時候,節點i的所有兒子的權值都會加 -val。注意當你給節點i的兒子的權值加 -val 時,節點i的這個兒子的所有兒子的權值都會加 -(-val),以此類推。樣例說明可以很好地幫助你理解這個性質。
有2種操作:
操作(a).“1 x val”表示給節點x的權值加val。
操作(b).“2 x”輸出節點x當前的權值。
為了幫助小L更好地理解這棵樹,你必須處理m個操作。
輸入
第一行包含2個整數n和m。
第二行包含n個整數a1,a2,…,an(1≤ai≤1000)。
接下來的n-1行,每行兩個整數u和v(1≤u接下來的m行,每行包含2種操作的一種。每個操作都保證1≤x≤n,1≤val≤1000。
輸出
對于每個操作(b),輸出一個整數,表示節點x當前的權值。
輸入樣例
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說明
【輸入輸出樣例說明】
初始各個節點的權值依次為[1,2,1,1,2]。
第一個操作給節點2的權值增加3,會給節點2的兒子4、5的權值增加-3。此時各個節點的權值變成[1,5,1,-2,-1]。
第二個操作給節點1的權值增加2,會給節點1的兒子2、3的權值增加-2,然后會給節點2的兒子4、5的權值增加-(-2)。各個節點的權值變成[3,3,-1,0,1]。
【數據說明】
對于50%的數據,1≤n≤2000,1≤m≤2000。
對于100%的數據,1≤n≤100000,1≤m≤100000。
解題思路
80分思路1:
當給某個點加值時,dfs下去,要輸出時,直接輸出
#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)//子節點dfs(a[i].to,-d);//數字翻轉 } 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;//存儲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:
給某個點價值時,先存下來,等輸出時,再往父節點搜
#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);//繼續往上 } 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;//記錄父節點}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));//往父節點搜} }正解
按奇偶性分下類
然后樹狀數組修改即可(懶)
總結
以上是生活随笔為你收集整理的【树状数组】【dfs】树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一键生成广告图片,亚马逊推出“卖家专用”
- 下一篇: 初一模拟赛总结(3.16)