Автор задачі: | Hadi Takla (TaklaOI) |
Підготував: | Hadi Takla (TaklaOI) |
Відредагував: | Hadi Takla (TaklaOI) |
Розв'язок
Спочатку спростимо задану операцію.
Коли ми беремо відрізок , спочатку ми встановлюємо x = a_l \& a_{l+1} \& ... \& a_r, що означає, що містить лише спільні біти на відрізку (l,r), тому коли ми замінюємо кожен елемент a_i на відрізку на a_i \oplus x, ми вимикаємо спільні біти на цьому відрізку.
Тепер нам потрібно мінімізувати побітове або масиву.
Припустимо, нам потрібно вимкнути біт в результаті або, це означає, що ми повинні вимкнути всі входження біта в масиві .
Нехай — перший індекс, де біт увімкнено, — останній індекс, де біт увімкнено.
Ми можемо вимкнути біт у фінальній відповіді тоді і тільки тоді, коли біт є спільним на відрізку (fr[i] , lst[i]). Чому?
Оскільки — перший індекс, де біт увімкнено, а — останній індекс, де біт увімкнено, то будь-який відрізок (), де l < fr[i] або r > lst[i], не матиме біт як спільний біт.
І будь-який відрізок (l , r), де l > fr[i] або r < lst[i], не вплине на значення фінальної відповіді.
Тому єдиним відрізком-кандидатом є fr[i] , lst[i].
Ми можемо перебрати всі бітів і для кожного біта спробувати застосувати операцію на fr[i] , lst[i], а потім взяти мінімальну відповідь.
Часова складність: \mathcal{O}(30 \cdot n).
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define F first
#define S second
using namespace std;
const int N = 2e5 + 1;
const int M = 1e9 + 7;
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int tc = 1;
cin>>tc;
while(tc--)
{
int n;
cin>>n;
int a[n+1] , ans = 0;
for(int i=1;i<=n;i++){
cin>>a[i];
ans |= a[i];
}
int fr[32]={0},lst[32]={0};
for(int i=1;i<=n;i++)
{
for(int j=0;j<=30;j++)
{
if(a[i] & (1LL<<j))
lst[j] = i;
}
}
for(int i=n;i>=1;i--)
{
for(int j=0;j<=30;j++)
{
if(a[i] & (1LL<<j))
fr[j] = i;
}
}
for(int j=0;j<=30;j++)
{
int x = (1LL<<31)-1;
for(int i=fr[j];i<=lst[j];i++)
x &= a[i];
for(int i=fr[j];i<=lst[j];i++)
a[i] ^= x;
int cur = 0;
for(int i=1;i<=n;i++)
cur |= a[i];
for(int i=fr[j];i<=lst[j];i++)
a[i] ^= x;
ans = min(ans , cur);
}
cout<<ans<<endl;
}
}