B AND Sorting
点此进入题面
题意:
给出一个排列,给定一个数 X
,每次操作只能交换 i & j = X
两个位置 的数字,问:X
最大为多少,能通过这种操作 让序列变得有序。
思路:
如果一个数 p[i] ≠ i
,那么一定要交换,所以必须有 X & p[i] = X
。
令 Y
=
所有不在它原本位置的 p[i]
的按位与,则 X ≤ Y
。
实际上可以让 X = Y
。因为我们可以把 Y
这个数字拿来当中介。如果要交换 p[i]
,p[j]
,我们可以先让 p[i]
和 Y
交换,Y
和 p[j]
交换,最后 Y
和 p[i]
交换。
将 所有位置不正确的元素 相与 的结果即为 本题答案。
时间复杂度:
O ( n ) O(n) O(n)
代码:
#define _CRT_SECURE_NO_WARNINGS 1
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#include <bits/stdc++.h>
using namespace std;
//#define int long long
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef pair<int, int> pii;
typedef map<int, int> mi;
typedef vector<ll> vll;
typedef pair<ll, ll> pll;
#define pb push_back
#define pp pop_back
#define x first
#define y second
const int N = 2e5 + 10;
int n;
int p[N];
signed main()
{
int T = 1; cin >> T;
while (T--)
{
cin >> n;
for (int i = 0; i < n; ++i) scanf("%d", &p[i]);
int ans = (1 << 30) - 1; //根据 “任何数与 1 相与都为其本身” 这一原则,我们可以先将答案设置为一个较大的,且二进制表示全为 1 的数
for (int i = 0; i < n; ++i)
{
if (p[i] != i)
{
ans &= p[i];
}
}
cout << ans << '\n';
}
return 0;
}