神仙題吧,很有東西
看了題解才會做的
先提取有用資訊:
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...