给出一个长度为n的数列,你每一次可以随意交换其中两个数字的位置。问你至少交换几次,才能使得这个数列是个单调递增数列。
最多50W个数据 离散化 存到线段树中
单点更新 成段查找即可
#include "iostream"
#include "algorithm"
using namespace std;
struct node
{
int x,id;
} num[501000];
int a[501000];
struct comp
{
int l,r;
__int64 sum;
} data[1200001];
bool cmp(const node a,const node b)
{
return a.x<b.x;
}
void build(int l,int r,int k)
{
int mid;
data[k].l=l;
data[k].r=r;
data[k].sum=0;
if (l==r) return ;
mid=(l+r)/2;
build(l,mid,k*2);
build(mid+1,r,k*2+1);
return ;
}
__int64 search(int l,int r,int k)
{
int mid;
if (data[k].l==l && data[k].r==r)
return data[k].sum;
mid=(data[k].l+data[k].r)/2;
if (r<=mid) return search(l,r,k*2);
else
if (l>mid) return search(l,r,k*2+1);
else
return search(l,mid,k*2)+search(mid+1,r,k*2+1);
}
void updata(int n,int k)
{
int mid;
if (data[k].l==n && data[k].r==n)
{
data[k].sum=1;
return ;
}
mid=(data[k].l+data[k].r)/2;
if (n<=mid) updata(n,k*2);
else updata(n,k*2+1);
data[k].sum=data[k*2].sum+data[k*2+1].sum;
}
int main()
{
int n,i,k;
__int64 ans;
while (scanf("%d",&n)!=EOF)
{
if (n==0) break;
for (i=0;i<n;i++)
{
scanf("%d",&num[i].x);
num[i].id=i;
}
sort(num,num+n,cmp);
k=0;
for (i=0;i<n;i++)
a[num[i].id]=k++;
build(0,n-1,1);
ans=0;
for (i=0;i<n;i++)
{
ans+=search(a[i],n-1,1);
updata(a[i],1);
}
printf("%I64d\n",ans);
}
return 0;
}