bzoj3192 [JLOI2013]删除物品

来源:互联网 发布:应用程序的端口号干什 编辑:程序博客网 时间:2024/05/16 09:10
3192: [JLOI2013]删除物品

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 668  Solved: 400
[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

Source

 

【思路】

         区间求和+单点修改。

         十分巧妙地重组数据,例如将样例重组为541273,给定两个指针t1/t2,分别指向两堆的top,这样所谓的移动操作就变成了堆顶指针的滑动了。存在设1,单点修改,BIT求和即可。

         注意ans为long long。

【代码】

         

 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 6 using namespace std; 7  8 typedef long long LL; 9 const int maxn = 100000+10;10 11 int read() {12     char c=getchar();13     while(!isdigit(c)) c=getchar();14     int x=0;15     while(isdigit(c)) {16         x=x*10+c-'0';17         c=getchar();18     }19     return x;20 }21 22 int a[maxn],rank[maxn],tmp[maxn];23 int n,m,t1,t2;24 25 int cmp(const int& i,const int& j) { return a[i]>a[j];26 }27 28 int c[maxn];29 int lowbit(int x) { return x&(-x);30 }31 void Add(int x,int d) {32     while(x<=n) {33         c[x]+=d;34         x+=lowbit(x);35     }36 }37 int Sum(int x) {38     int res=0;39     while(x>0) {40         res+=c[x];41         x-=lowbit(x);42     }43     return res;44 }45 int main() {46     n=read(),m=read();47     t1=n,t2=t1+1;48     FOR(i,1,n) a[i]=read();49     FOR(i,n+1,n+m) a[i]=read();50     FOR(i,1,n) tmp[i]=a[n-i+1];51     FOR(i,1,n) a[i]=tmp[i];52     n += m;53     FOR(i,1,n) rank[i]=i,Add(i,1);54     55     sort(rank+1,rank+n+1,cmp);56     57     LL ans=0;                 //long long型 58     FOR(i,1,n) {59         int t=rank[i];60         if(t>=t2) {61             ans+=Sum(t)-Sum(t2-1)-1;62             Add(t,-1);63             t2=t;t1=t2-1;64         }65         else {66             ans+=Sum(t1)-Sum(t-1)-1;67             Add(t,-1);68             t1=t; t2=t1+1;69         }70     }71     printf("%lld\n",ans);72     return 0;73 }

 

0 0