文章出處
Submit: 872 Solved: 508
[Submit][Status][Discuss]
View Code
文章列表
3192: [JLOI2013]刪除物品
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 872 Solved: 508
[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
1
4
5
2
7
3
Sample Output
6
HINT
1<=N1+N2<=100000
Source
開始水博
接著上一個紀元講的內容
這道題其實模擬就好,看題解前最好手動模擬一下
(快去模擬!)
那么在模擬時,容易想到的優化是把兩個棧的棧頂接上,直接維護數列
維護時可以排序一遍,得出每個元素的順序
比如對于5 4 1 2 7 3
排完序就是3 4 6 2 1 5
接下來維護一個01序列,表示第i位是否被彈出
那么答案就是按照排序后序列求01區間和(其實有好多細節哦)
取出一個數后置零即可

1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<algorithm> 5 #define LL long long 6 using namespace std; 7 int rank[101000],num[101000]; 8 int bit[101000],n; 9 int lb(int x){ 10 return x&(-x); 11 } 12 int cmp(const int a,const int b){ 13 return num[a]>num[b]; 14 } 15 LL q(int x){ 16 LL ans=0; 17 while(x){ 18 ans+=bit[x]; 19 x-=lb(x); 20 } 21 return ans; 22 } 23 int c(int x,int v){ 24 while(x<=n){ 25 bit[x]+=v; 26 x+=lb(x); 27 } 28 return 0; 29 } 30 int main(){ 31 int a,b; 32 scanf("%d %d",&a,&b); 33 n=a+b; 34 for(int i=1;i<=n;i++)rank[i]=i; 35 rank[0]=a; 36 for(int i=a;i;--i)scanf("%d",&num[i]); 37 for(int i=1;i<=b;i++)scanf("%d",&num[i+a]); 38 sort(rank+1,rank+n+1,cmp); 39 for(int i=1;i<=n;i++)c(i,1); 40 LL ans=0; 41 for(int i=1;i<=n;i++){ 42 if(rank[i]>rank[i-1])ans+=q(rank[i]-1)-q(rank[i-1]); 43 else ans+=q(rank[i-1])-q(rank[i]);//????????????????rank????? 44 c(rank[i],-1); 45 } 46 printf("%lld\n",ans); 47 return 0; 48 }
文章列表
全站熱搜