【树状数组】BZOJ3192 [JLOI2013]删除物品

非常巧妙的转化,简化了题目

题面在这里

首先可以发现,无论怎么移动,所有元素的相对位置是不变的

所以可以把两个堆转化为一个序列(第一个堆倒置)

然后其实就是对临界指针的移动了

用树状数组维护每次移动过程经过多少没有被删除的元素

示例程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
#define abs_(x) ((x)>0?(x):-(x))

const int maxn=100005;
int N,M,n,a[maxn],BIT[maxn];
ll ans=0;
pair<int,int> b[maxn];
#define lowbit(x) ((x)&-(x))
inline void ist(int x,int w) {for (int i=x;i<=n;i+=lowbit(i)) BIT[i]+=w;}
inline int ask(int x) {int res=0;for (int i=x;i;i-=lowbit(i)) res+=BIT[i];return res;}
int main(){
scanf("%d%d",&N,&M);
for (int i=N;i;i--) scanf("%d",&a[i]),b[++n]=make_pair(a[i],N-n+1);
for (int i=1;i<=M;i++) scanf("%d",&a[i+N]),b[++n]=make_pair(a[i+N],n);
sort(b+1,b+1+n);
for (int i=1;i<=n;i++) ist(i,1);
for (int t=n,i=N;t;t--)
if (i<b[t].second) ans+=ask(b[t].second-1)-ask(i),i=b[t].second-1,ist(b[t].second,-1);
else ans+=ask(i)-ask(b[t].second),i=b[t].second,ist(b[t].second,-1);
printf("%lld",ans);
return 0;
}