删除物品

HYSBZ 3192:http://www.lydsy.com/JudgeOnline/problem.php?id=3192

题意:中文题。

题解:把两个堆头对头并起来。例如样例:5 4 1 2 7 3,然后两堆之间的设置mid,对于每一次删除最大的来说,例如,删除7,我们要知道上一次mid的位子,然后两个坐标的差值就是这一次移动的步数,前提是7到mid之间的元素,在这之前没有删除,所以要统计这两个数之间的数。可以用树状数组来维护。具体的看代码。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 struct Node{
 7   int nu;
 8   int data;
 9   bool operator<(const Node a)const{
10     return data<a.data;
11   }
12 }num[100002];
13 int n1,n2,n,mi;
14 long long ans;
15 int a[100002];
16 int c[100002];
17 int lowbit(int x){
18   return x&(-x);
19 }
20 void add(int x){
21    while(x<=n){
22     c[x]+=1;
23     x+=lowbit(x);
24    }
25 }
26 int getsum(int x){
27    int ans=0;
28    while(x>=1){
29       ans+=c[x];
30       x-=lowbit(x);
31    }
32   return ans;
33 }
34 int main(){
35    scanf("%d%d",&n1,&n2);
36    n=n1+n2;mi=n1;ans=0;
37    for(int i=n1;i>=1;i--)scanf("%d",&a[i]);
38    for(int i=n1+1;i<=n1+n2;i++)scanf("%d",&a[i]);
39    for(int i=1;i<=n1+n2;i++){
40      num[i].nu=i;
41      num[i].data=a[i];
42    }
43     sort(num+1,num+n+1);
44    memset(c,0,sizeof(c));
45    for(int i=n;i>=1;i--){
46      int x=num[i].nu;
47      //printf("%d
",x);
48      if(mi>=x){
49        ans+=(mi-x)-(getsum(mi)-getsum(x));
50        mi=x;
51        add(x);
52      }
53      else{
54       ans+=(x-1-mi)-(getsum(x-1)-getsum(mi));
55        mi=x-1;
56        add(x);
57      }
58    }
59    printf("%lld
",ans);
60  
61  
62 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3863698.html