題目描述
給定乙個長度為n的數列ai,求ai的子串行bi的最長長度,滿足bi&bi-1!=0(2<=i<=len)。
說明對於100%的資料,1<=n<=100000,ai<=10^9。
錯誤日誌: 沒搞清 每一位的dp值如何更新記錄陣列
乙個數 \(a\) 可以接在數 \(b\) 後面, 當他們在二進位制下有相同位同為 \(1\) 時成立
這啟發我們可以這樣更新: 對於新的數 \(x\) 的每個 \(1\) 位,向前尋找乙個最長的數為前乙個轉移
可這樣複雜度任然無法保證
而想想又發現, 不優值一定不考慮, 我們只用對每一位含 \(1\) 位 儲存最大長度即可
我們設定乙個陣列 \(ton[j]\) 表示到目前為止, 二進位制下第 \(j\) 位為 \(1\) 的最長長度
更新第 \(i\) 個數 \(x\) 時, 當 \(x\) 的第 \(j\) 位為 \(1\) 時, 有 \(dp[i] = max(dp[i], ton[j] + 1)\)
更新完答案後需要返回來更新 \(ton[j]\), 當 \(x\) 的第 \(j\) 位為 \(1\) 時, 有 \(ton[j] = max(ton[j], dp[i])\)
#include#include#include#include#include#include#define ll long long
#define rep(i, x, y) for(int i = (x);i <= (y);i++)
using namespace std;
int rd()
while(c >= '0' && c <= '9')
return flag * out;
}const int maxn = 200019;
int num;
int dp[maxn], ton[39];
int ans;
int main()
rep(j, 1, 31)
ans = max(ans, dp[i]);
} printf("%d\n", ans);
return 0;
}
P4310 絕世好題
給定乙個長度為n的數列ai,求ai的子串行bi的最長長度,滿足bi bi 1 0 2 i len 輸入格式 輸入檔案共2行。第一行包括乙個整數n。第二行包括n個整數,第i個整數表示ai。輸出格式 輸出檔案共一行。包括乙個整數,表示子串行bi的最長長度。輸入樣例 1 3 1 2 3 輸出樣例 1 2 ...
P4310 絕世好題 題解
第一次看這道題首先想到的就是時間複雜度為 n 的求最長上公升子串行 for int i 1 i n i 這樣寫會超時 所以我們考慮更優秀的演算法,突破口就是位運算 題目中的操作是按位與,所以我們可以把乙個數的每乙個二進位制位分別拆分進行計算 我們設 f i 為當前二進位制位為 i 時滿足要求的最長長...
P4310 絕世好題 DP 題解
題面傳送門 p4310 絕世好題 第一眼以為是套路n2 dp,一看資料範圍1e5,直接懵逼5min 其實挺簡單的,題目也不錯 仔細想想挺簡單的,因為b i b i 1 0,那至少有一位二進位制位b i 和b i 1 均為1。然後我們考慮列舉bi的每一位二進位制1,在所有這一位也為1的數中,取以該數結...