这道题我同时维护了两个线段树,最后A掉了。
在第一个树中修改每次查询树中的最小值,然后在第二个树中查到这个最小值所在的位置在之前的操作中右移过多少次,两者相加即为这个值当前所在的位置,在根据这个值要交换到的位置计算出需要交换多少次。需要注意的是在维护第二个树的时候,每次更新区间的值是从1到a[1].k-kk,这是因为当前值的交换是一直往左边进行的,不会对在其右边的元素的位置有影响。
这两个线段树可以合并成一个,不过合并了按我这种写法也不会让代码简洁多少。
#include<stdio.h>
#include<string.h>
#define N 500005
#define M 1000000005
typedef __int64 LL;
LL sum;
int c[N];
struct node
{
int x,y;
int num,k;
}a[N*3];
struct point
{
int x,y;
int flag;
}b[N*3];
void CreatTree(int t,int x,int y)
{
a[t].x=x;a[t].y=y;
if(x==y)
{
a[t].num=c[x];
a[t].k=x;
return ;
}
int temp=t*2;
int mid=(x+y)/2;
CreatTree(temp,x,mid);
CreatTree(temp+1,mid+1,y);
if(a[temp].num<a[temp+1].num)
{
a[t].num=a[temp].num;
a[t].k=a[temp].k;
}
else
{
a[t].num=a[temp+1].num;
a[t].k=a[temp+1].k;
}
return ;
}
void CSubTree(int t,int x,int y)
{
b[t].x=x;b[t].y=y;b[t].flag=0;
if(x==y)
return ;
int temp=t*2;
int mid=(b[t].x+b[t].y)/2;
CSubTree(temp,x,mid);
CSubTree(temp+1,mid+1,y);
return ;
}
void InsertTree(int t,int x,int k)
{
if(a[t].x==a[t].y&&a[t].x==x)
{
a[t].num=k;
return ;
}
int temp=t*2;
int mid=(a[t].x+a[t].y)/2;
if(x<=mid)
InsertTree(temp,x,k);
else
InsertTree(temp+1,x,k);
if(a[temp].num<a[temp+1].num)
{
a[t].num=a[temp].num;
a[t].k=a[temp].k;
}
else
{
a[t].num=a[temp+1].num;
a[t].k=a[temp+1].k;
}
return ;
}
void ISubTree(int t,int x,int y)
{
if(b[t].x==x&&b[t].y==y)
{
b[t].flag++;
return ;
}
int temp=t*2;
int mid=(b[t].x+b[t].y)/2;
if(b[t].flag)
{
b[temp].flag+=b[t].flag;
b[temp+1].flag+=b[t].flag;
b[t].flag=0;
}
if(y<=mid)
ISubTree(temp,x,y);
else if(x>mid)
ISubTree(temp+1,x,y);
else
{
ISubTree(temp,x,mid);
ISubTree(temp+1,mid+1,y);
}
return ;
}
int FSubTree(int t,int x)
{
if(b[t].x==b[t].y&&b[t].x==x)
{
return b[t].flag;
}
int temp=t*2;
int mid=(b[t].x+b[t].y)/2;
if(b[t].flag)
{
b[temp].flag+=b[t].flag;
b[temp+1].flag+=b[t].flag;
b[t].flag=0;
}
if(x<=mid)
return FSubTree(temp,x);
else
return FSubTree(temp+1,x);
}
int main()
{
int n;
while(scanf("%d",&n),n)
{
int i;
for(i=1;i<=n;i++)
scanf("%d",&c[i]);
CreatTree(1,1,n);
CSubTree(1,1,n);
sum=0;
int cnt;
cnt=1;
while(a[1].num!=M)
{
int kk;
kk=FSubTree(1,a[1].k);
a[1].k+=kk;
sum+=a[1].k-cnt;
ISubTree(1,1,a[1].k-kk);
InsertTree(1,a[1].k-kk,M);
cnt++;
}
printf("%I64d\n",sum);
}
return 0;
}