3192: [JLOI2013]删除物品

3192: [JLOI2013]删除物品

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;
}

你可能感兴趣的:(3192: [JLOI2013]删除物品)