【HDU】5735 Born Slippy DP+折半列舉優化
阿新 • • 發佈:2020-10-07
題意
給出一個具有 n 個節點的樹,每個節點都有一個權值 w,現在對於每個節點 s 要求出一個\(f(s)\)
- 對於節點 s,找到一個節點序列,\(v_1,v_2,v_3...v_m\),\(v_1 = s\),\(v_{i+1}\)是\(v_i\)的祖先節點
- \(f(s)=w_s+\sum_{i=2}^{m}{w_{v_i}\ opt\ w_{v_{i-1}}} f(s) 要儘可能的大\)
輸出\(\sum_{i=1}^n i*f(i)\)
思路
我們用 \(dp[i]\) 表示\(f(i)-w_i\)
先不考慮樹上,把題目轉移到一個整數陣列上來。
那麼 \(dp[i]=max(dp[i],dp[j]+w_j\ opt \ \ w_i)(j<i)\)
樹上同理,但是這個轉移方程的複雜度太高了。
愣是想不到如何把 \(O(n^2)\) 變成 \(O(logn)\)。
看題解發現是真滴騷。
在我理解來,就是把遍歷 \(j\) 的過程變成了遍歷 \(w_j\) 的可能取值,但是 \(w_j\) 有 \(2^{16}\)種情況,也不可能遍歷,我們通過一個數組 \(f[a][b]\) 變得只需列舉 \(2^8\) 來降低複雜度 。
總體複雜度為 \(N*2^8\)即\(2^{24}\)
程式碼
/* * @Autor: valk * @Date: 2020-08-11 12:38:37 * @LastEditTime: 2020-09-28 17:19:07 * @Description: 如果邪惡 是華麗殘酷的樂章 它的終場 我會親手寫上 晨曦的光 風乾最後一行憂傷 黑色的墨 染上安詳 */ #include <algorithm> #include <iostream> #include <map> #include <math.h> #include <queue> #include <set> #include <stack> #include <stdio.h> #include <string.h> #include <string> #include <vector> #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int mod = 1e9 + 7; const int seed = 12289; const double eps = 1e-6; const ll INF=0x8f8f8f8f8f8f8f8f;//-1886417009 const int inf = 0x3f3f3f3f; const int N = 1e5 + 10; vector<int>vec[N]; int w[N]; ll rel[N][260],f[260][260],ans; char op[5]; int opt(int a,int b) { if(op[0]=='A') return a&b; if(op[0]=='X') return a^b; return a|b; } void dfs(int pos) { int a=w[pos]>>8,b=w[pos]&255; ll maxn=0; for(int i=0;i<256;i++){ if(f[i][b]!=INF) maxn=max(maxn,f[i][b]+(opt(i,a)<<8)); } ans=(ans+1LL*(maxn+w[pos])%mod*pos%mod)%mod; for(int i=0;i<256;i++){ rel[pos][i]=f[a][i]; f[a][i]=max(f[a][i],maxn+opt(b,i)); } for(int i=0;i<vec[pos].size();i++){ dfs(vec[pos][i]); } for(int i=0;i<256;i++){ f[a][i]=rel[pos][i]; } } int main() { int T; scanf("%d",&T); while(T--){ int n; scanf("%d%s",&n,op); ans=0; memset(f,INF,sizeof(f)); for(int i=1;i<=n;i++){ vec[i].clear(); } for(int i=1;i<=n;i++){ scanf("%d",&w[i]); } for(int i=2;i<=n;i++){ int fa; scanf("%d",&fa); vec[fa].pb(i); } dfs(1); printf("%lld\n",ans); } return 0; }