bzoj4446 Scoi2015 小凸玩密室

2022-05-19 05:32:51 字數 1389 閱讀 3410

神仙題吧,很有東西

看了題解才會做的

先提取有用資訊:

1、這個密室是一棵有n個節點的完全二叉樹

2、在點燈的過程中,要保證任意時刻所有被點亮的燈泡必須連通

3、在點亮乙個燈泡後必須先點亮其子樹所有燈泡才能點亮其他燈泡

所以get到資訊

1、樹高嚴格\(logn\)

2、點亮的燈泡組成乙個聯通塊

3、點亮乙個燈泡後一定是往兒子走

然而我依然不會,借助題解才設出了狀態

\(f[i][j][0]\)表示第一次點第\(i\)個節點,點亮完\(i\)的子樹後點亮\(i\)的第\(j\)個祖先的最小花費

\(f[i][j][1]\)表示第一次點第\(i\)個節點,點亮完\(i\)的子樹後點亮\(i\)的第\(j\)個祖先的另乙個兒子的最小花費(就是\(i\)節點所在子樹的兄弟節點)

預處理出每個節點的所有祖先,

然後考慮怎麼轉移,分三種情況

1、沒有兒子的,算出它到它的所有祖先的花費

2、只有左兒子或只有右兒子的,只能往左或者右走

3、有兩個兒子的,分情況討論一下

由於第一次點的點不確定,所以要列舉一下,然後一直往上走就行了,碰到有2個兒子的判斷一下,就行了

方程我就不寫了,這位大佬方程寫的很詳細傳送門

時間複雜度\(o(nlogn)\)

**:

#include#include#include#includeusing namespace std;

#define int long long

void read(int &x)

#define rg register

const int maxn=2e5+10;

int n,a[maxn],b[maxn],l[maxn],r[maxn],g[maxn][20],f[maxn][20][2],dep[maxn],ans;

void prepare(int x)

void dfs(int x)

else f[x][i][1]=1e18;

} }else

}else if(r[x]&&!l[x])

}else

} }}

signed main()

prepare(1),dfs(1);ans=f[1][0][0];

for(rg int i=2;i<=n;i++)

else

}las=now,now=g[now][1];

if(l[now]&&r[now])

else if(las!=i)val+=(dep[las]-dep[now])*a[now];

ans=min(ans,val);

} printf("%lld\n",ans);

}

BZOJ4446 Scoi2015 小凸玩密室

用ui,j表示走完i的子樹後走到i的深度為j的祖先的兄弟的最小代價 用vi,j表示走完i的子樹後走到i的深度為j的祖先的最小代價,用u算出v。列舉起點,計算答案。include includeusing std min typedef long long ll const int n 2e5 5 l...

BZOJ 1079 SCOI2008 著色方案

題目 分析 一看就覺得是dp或者直接排列組合公式或者容斥?我就只想到dp的,我們用dp i j 表示前i種顏色,排列出有j對相鄰一樣顏色的方案數。當出現乙個新的顏色時,我們把這個顏色插板法插進去,我們要列舉插入的方式,可能插到相鄰顏色一樣的中間,或者不是,然後進行狀態轉移.具體看 include i...

BZOJ1066 SCOI2007蜥蜴 最大流

挺顯然的最大流,源向所有有蜥蜴的點連inf邊,所有點拆成入點和出點,入店向出點連流量為高度的邊,限制流量,所有可以一步跳出去的點向匯連inf邊,跑最大流就行了。include include include define inf 99999999 define maxn 1005 using nam...