题意:给出一个n的排列,你可以对任意区间进行翻转,花费的代价是r-l+1。你可以进行任意次操作使得最后满足p[i]=i。问,所以操作异或和的最小值与最大值分别是多少。
官方题解有详细的推导过程
赛时只想了想最小值,可以用多个代价为2的操作组成,最后结果为0或2,答案取决于逆序对个数。再根据样例猜猜最大值其实就有了,最大值的方向也很好猜,最大就是最高位与n相同,然后全1,然后再想一想应该就有了,但是不知道在干嘛。
对于不限制操作次数,但是对代价有要求的,而且是异或。所以应该想到通过等价操作,平白搞出来值用来异或,这应该是正常的思路。然后异或按位去思考,大概就是这样。
#include<bits/stdc++.h>
#define N 103500
using namespace std;
long long p,T,n,ans,total,a[N],c[N];
long long lowbit(long long x)
{
return x&(-x);
}
void add(int i,int x)
{
while (i<=n)
{
c[i]+=x;
i+=lowbit(i);
}
}
long long getsum(long long i)
{
long long sum=0;
while (i>0)
{
sum+=c[i];
i-=lowbit(i);
}
return sum;
}
int main()
{
cin>>T;
while (T--)
{
ans=0;
cin>>n;
for (int i=1;i<=n;i++) c[i]=0;
for (int i=1;i<=n;i++)
{
cin>>a[i];
add(a[i],1);
ans+=getsum(n)-getsum(a[i]);
}
if (n==1){cout<<"0"<<" "<<"1"<<endl;continue;}
p=1;
while (p<=n)
{
p*=2;
}
total=p-1;
if (ans%2==0) cout<<"0"<<" "<<total-2<<endl;
else cout<<"2"<<" "<<total<<endl;
}
}