日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【牛客 - 303K第十五届浙江大学宁波理工学院程序设计大赛(同步赛)】Technology Tree(树形dp,tricks)

發布時間:2023/12/10 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【牛客 - 303K第十五届浙江大学宁波理工学院程序设计大赛(同步赛)】Technology Tree(树形dp,tricks) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:
?

在星際爭霸(StarCraft)中,有3個種族。對于任意一個種族,他們的建筑建造都是有一個順序的。這個順序正好是一個樹形結構,我們稱之為"科技樹"(Technology tree)。

在科技樹中,只有一個建筑是不需要前置建筑的,我們把這個建筑的編號設為1。其他的建筑,有且僅有一個前置建筑。

比如建筑2的前置建筑為建筑1,意思是只有先建造了建筑1,才能建造建筑2。

一個種族有n個建筑,建筑1沒有前置建筑,建筑i(2≤i≤n)的前置建筑為f。每個建筑的建造都需要費用,建筑i(1≤i≤n)的建造花費為a晶體礦和b高能瓦斯。

現在tokitsukaze想知道,如果想要建造建筑x,總共需要消耗多少晶體礦和高能瓦斯。

輸入描述:

第一行包含一個T(T≤10),表示T組數據。對于每組數據: 第一行包含兩個正整數n,q(1≤n,q≤20000),表示有n個建筑和q次查詢。 接下來n行,每行包含兩個整數a,b(0≤a,b≤300),表示建造建筑i需要花費a晶體礦和b高能瓦斯。 接下來一行,包含n-1個正整數f(1≤f≤n)。第i個(1≤i<n)正整數fi(1≤fi<i)表示建筑i+1的前置建筑為fi。 接下來q行,每行包含一個正整數x,表示詢問。

輸出描述:

對于每個詢問,輸出一行,包含兩個整數c,d(用空格隔開),表示如果想要建造建筑x,總共需要消耗c晶體礦和d高能瓦斯。

?

示例1

輸入

復制

1 4 4 1 5 10 100 200 50 66 88 1 1 2 1 2 3 4

輸出

復制

1 5 11 105 201 55 77 193

說明

第一組樣例:如果想要建造建筑1,總共需要消耗1晶體礦和5高能瓦斯。如果想要建造建筑2,需要先建造建筑1,總共需要消耗1+10晶體礦和5+100高能瓦斯。 如果想要建造建筑3,需要先建造建筑1,總共需要消耗1+200晶體礦和5+50高能瓦斯。 如果想要建造建筑4,需要先建造建筑1和建筑2,總共需要消耗1+10+66晶體礦和5+100+88高能瓦斯。

解題報告:

? ?就是記憶化一個樹形dp就行了唄,,不算難想。但是因為輸入的巧妙,這題可以用巧妙的解法,詳見下面Qls的思路。OrzOrz

?

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e4 + 5; struct Node {int j,g; } node[MAX]; int pre[MAX]; ll dpg[MAX],dpj[MAX]; ll dfsg(int cur,int root) {if(cur == 1) return dpg[1] = node[1].g ;if(dpg[cur] != -1) return dpg[cur];dpg[cur]=0;dpg[cur] += dfsg(pre[cur],cur);dpg[cur] += node[cur].g;return dpg[cur]; } ll dfsj(int cur,int root) {if(cur == 1) return dpj[1] = node[1].j ;if(dpj[cur] != -1) return dpj[cur];dpj[cur]=0;dpj[cur] += dfsj(pre[cur],cur);dpj[cur] += node[cur].j;return dpj[cur]; } int main() {int t,a,b,q,n;cin>>t;while(t--) {memset(dpj,-1,sizeof dpj);memset(dpg,-1,sizeof dpg); //chushihuascanf("%d%d",&n,&q);for(int i = 1; i<=n; i++) {scanf("%d%d",&node[i].j,&node[i].g);}for(int i = 2,x; i<=n; i++) {scanf("%d",&x);pre[i]=x;}for(int i = 1; i<=n; i++) {dfsg(i,-1);dfsj(i,-1);}int x;while(q--) {scanf("%d",&x);printf("%lld %lld\n",dpj[x],dpg[x]);}}return 0 ;}

其實這個代碼完全可以返回一個結構體或者用pair或者用兩個引用,,但是這里因為懶惰,,沒有改代碼,(因為第一次寫的時候不知道要求輸出 晶體礦和高能瓦斯 分開輸出。所以就寫了一個dp,,然后發現輸出格式后又懶得改然后就直接復制一波,改改變量就交了、)

Qls思路:(因為這題是按照順序讀入的:fi(1≤fi<i)? ?所以可以這么寫,,也算是個小技巧吧,,,不這么讀入的話,就不能這么狀態轉移了,,所以還是老老實實寫樹上的吧)

#include<bits/stdc++.h> using namespace std; const int MAXN=20005; int a[MAXN],b[MAXN]; int main() {int T;scanf("%d",&T);while(T--){int n,q;scanf("%d%d",&n,&q);for(int i=1;i<=n;i++)scanf("%d%d",&a[i],&b[i]);for(int i=2;i<=n;i++){int f;scanf("%d",&f);a[i]+=a[f],b[i]+=b[f];}for(int i=1;i<=q;i++){int x;scanf("%d",&x);printf("%d %d\n",a[x],b[x]);}}return 0; }

ps:神仙就是神仙,,,一小時秒了九個題,,強勢Rank1、、OrzOrz

總結

以上是生活随笔為你收集整理的【牛客 - 303K第十五届浙江大学宁波理工学院程序设计大赛(同步赛)】Technology Tree(树形dp,tricks)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。