删除物品
题意:中文题。
题解:把两个堆头对头并起来。例如样例: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\n",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\n",ans); 60 61 62 }