Hướng dẫn giải của Bedao Mini Contest 26 - Mảng OR
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Xét một vị trí ~r~ cố định, xét các hậu tố ~f_i~ ~=~ ~a_i~ ~|~ ~a_{i + 1}~ ~|~ ~\cdots~ ~|~ ~a_r~. Ta sẽ xem xét sự thay đổi của dãy hậu tố ~f~ khi thêm phần tử ~r + 1~.
Dễ thấy ~f_1 \ge f_2 \ge \cdots \ge f_r~. Giá trị của hậu tố tăng khi độ dài tăng. Cụ thể các bit ~1~ sẽ giữ nguyên và các bit ~0~ có thể thay đổi thành bit ~1~. Do đó chỉ có tối đa ~k~ giá trị phân biệt của dãy hậu tố, ~k~ là số lượng bit. Nếu ~f_{i - 1} = f_{i}~, ta chỉ cần giữ lại ~1~ giá trị ~f_i~. Khi đó ta có chiến thuật làm như sau:
Duyệt qua từng phần tử của dãy ~a~ từ trái qua phải và dùng một mảng ~m~ (hoặc set) để lưu các giá trị phân biệt của dãy hậu tố. Kích thước của mảng sẽ luôn nhỏ hơn hoặc bằng ~k~ (như phân tích trên);
Khi duyệt từ vị trí ~i - 1~ sang ~i~, thay đổi mảng ~m =~ ~m_1~, ~m_2~, ~\cdots~, ~m_t~ thành ~m =~ ~a_i~, ~m_1 | a_i~, ~m_2 | a_i~, ~\cdots~, ~m_t | a_i~;
Xoá bỏ các giá trị trùng lặp trong mảng ~m~ và thêm các giá trị này vào mảng kết quả.
#include<bits/stdc++.h> #define fr first #define sc second #define P pair<int,int> #define m_p make_pair #define pb push_back #define lowbit(x) (x&(-x)) #define int long long typedef long long ll; using namespace std; set<int> ans,now; signed main(){ ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); int n;cin>>n; for(int i=0;i<n;i++){ int x;cin>>x; now.insert(0); set<int> nw; for(set<int>::iterator it=now.begin();it!=now.end();it++){ int y=(*it); nw.insert((x|y)); ans.insert((x|y)); } now=nw; } cout<<ans.size()<<endl; return 0; }
Bình luận