Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 123 Solved: 77
[Submit][Status][Discuss]
Description
箱子再分配问题需要解决如下问题:
(1)一共有N个物品,堆成M堆。
(2)所有物品都是一样的,但是它们有不同的优先级。
(3)你只能够移动某堆中位于顶端的物品。
(4)你可以把任意一堆中位于顶端的物品移动到其它某堆的顶端。若此物品是当前所有物品中优先级最高的,可以直接将之删除而不用移动。
(5)求出将所有物品删除所需的最小步数。删除操作不计入步数之中。
(6)只是一个比较难解决的问题,这里你只需要解决一个比较简单的版本:
不会有两个物品有着相同的优先级,且M=2
Input
第一行是包含两个整数N1,N2分别表示两堆物品的个数。
接下来有N1行整数按照从顶到底的顺序分别给出了第一堆物品中的优先级,数字越大,优先级越高。
再接下来的N2行按照同样的格式给出了第二堆物品的优先级。
Output
对于每个数据,请输出一个整数,即最小移动步数。
Sample Input
3 3
1
4
5
2
7
3
Sample Output
6
HINT
1<=N1+N2<=100000
首先我想骂人》》》》》》
线段树;把两个堆的顶拼在一起,做一个指针指向左堆的顶,每次去除最大的数,并更新指针(fail)
详见代码
:
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<vector>
#include<math.h>
#include<queue>
#include<algorithm>
#define lson id*2
#define rson id*2+1
#define maxx 2000000
using namespace std;
struct node{long long v;long long mark;} tre[maxx];
long long a,b,c,d,n,m;
node arr[maxx];
int sta=-1;
int pushup(int id)
{
tre[id].v=tre[lson].v+tre[rson].v;
return 0;
}
int build(int id,int l,int r)
{
if (l>r) return 0;
if (l==r)
{
tre[id].v=1;
return 0;
}
int mid=(l+r)/2;
build(lson,l,mid);
build(rson,mid+1,r); pushup(id);
return 0;
}
inline void add(int id,int l,int r,int pos,int num)
{
if (l>r) return;
if (l==r && r==pos)
{
tre[id].v+=num;
return ;
}
int mid=(l+r)/2;
if (pos<=mid) add(lson,l,mid,pos,num);
if (pos>=mid+1) add(rson,mid+1,r,pos,num);
pushup(id);
return;
}
int cmp(node aa,node bb)
{
return aa.v>bb.v;
}
long long kk;
inline void query(int id,int l,int r,int L,int R)
{
if (l>r || L>R) return ;
if (l>=L && r<=R)
{
kk+=tre[id].v;
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);
return ;
}
int main()
{
cin>>n>>m;
for (int i=n;i>=1;i--)
{
scanf("%lld",&a);
arr[i].v=a;
arr[i].mark=i;
}
for (int j=n+1;j<=n+m;j++)
{
scanf("%lld",&a);
arr[j].v=a;
arr[j].mark=j;
}
build(1,1,m+n);
sort(arr+1,arr+1+n+m,cmp);
long long fail=n;
long long ans;
ans=0;
for (int i=1;i<=n+m;i++)
{
a=arr[i].mark;
kk=0;
if (fail<a)
{
query(1,1,m+n,fail+1,a-1);
fail=a-1;
}
else if (fail>a)
{
query(1,1,m+n,a+1,fail);
fail=a;
}
ans+=kk;
add(1,1,m+n,arr[i].mark,-1);
}
cout<<ans<<endl;
}