题目链接:
http://www.lydsy.com/JudgeOnline/problem.php?id=3192
题解:
我们发现将第一堆数的前i个数移到另一堆,即将第一堆数前i个数反向连接到第二堆数上,那么我们可以将第一堆数的开头连接在第二堆数的开头,记录当前堆顶的位置,而且需要的步数是当前,未完待续。。
代码:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<map>
#define maxn (100005)
#define lson (id*2)
#define rson (id*2+1)
using namespace std;
map<int,int>vis;
int tmp,b[maxn],num,n1,n2,a[maxn],tr[400005],w[maxn];
long long ans;
void pushup(int id)
{
tr[id]=tr[lson]+tr[rson];
return ;
}
void build(int id,int l,int r)
{
if (l>r) return ;
if (l==r)
{
tr[id]=1;
return ;
}
int mid=(l+r)/2;
build(lson,l,mid);
build(rson,mid+1,r);
pushup(id);
return ;
}
void query(int id,int l,int r,int L,int R)
{
if (l>r) return ;
if (l>=L && r<=R)
{
tmp+=tr[id];
return ;
}
int mid=(l+r)/2;
if (mid>=L) query(lson,l,mid,L,R);
if (mid+1<=R) query(rson,mid+1,r,L,R);
pushup(id);
return ;
}
void gai(int id,int l,int r,int x)
{
if (l>r) return ;
if (l==r && r==x)
{
tr[id]=0;
return ;
}
int mid=(l+r)/2;
if (mid>=x) gai(lson,l,mid,x);
if (mid+1<=x) gai(rson,mid+1,r,x);
pushup(id);
return ;
}
int main()
{
scanf("%d%d",&n1,&n2);
num=n1+n2+1;
for (int i=n1;i>=1;i--)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
for (int i=n1+2;i<=num;i++)
{
scanf("%d",&a[i]);
b[i]=a[i];
}
int mid=n1+1;
a[mid]=-1;
sort(b+1,b+1+num);
for (int i=1;i<num;i++)
{
vis[b[i+1]]=i;
// cout<<b[i+1]<<' ';
}
for (int i=1;i<=num;i++)
{
if (a[i]!=-1)
{
a[i]=vis[a[i]];
w[a[i]]=i;
}
}
// cout<<"khkhj"<<endl;
a[mid]=0;
build(1,1,num);
gai(1,1,num,mid);
// for (int i=1;i<=num;i++)
// cout<<w[i]<<endl;
for (int i=num-1;i>=1;i--)
{
int x=w[i];
tmp=0;
// cout<<" here 1 "<<endl;
if (x<=mid)
query(1,1,num,x+1,mid);
else
query(1,1,num,mid,x-1);
ans+=tmp;
mid=x;
gai(1,1,num,mid);
}
cout<<ans<<endl;
}