BZOJ 3192: [JLOI2013]删除物品(树状数组)
题面:
https://www.lydsy.com/JudgeOnline/problem.php?id=3192
题解:
首先每次一定是来回移动直到最大的到顶上。
所以我们可以将第两个堆的堆顶接起来形成一个队列。
然后相当于中间一个象征两堆分界的指针在来回移动。
用树状数组维护一下区间内删除了几个点。
代码:
1 #include<bits/stdc++.h>
2
3 using namespace std;
4
5 typedef long long ll;
6 const int maxn=100010;
7 ll ans,n,m,tr[maxn],mx;
8
9 struct node{
10 ll w,pos;
11 bool operator < (const node &b) const{
12 return w>b.w;
13 }
14 }f[maxn];
15
16 ll lowbit(ll x){
17 return x&-x;
18 }
19
20 void add(ll k,ll x){
21 for(int i=k;i<=mx;i+=lowbit(i))
22 tr[i]+=x;
23 }
24
25 ll ask(int k){
26 int sum=0;
27 for(int i=k;i;i-=lowbit(i))
28 sum+=tr[i];
29 return sum;
30 }
31
32 int main(){
33 scanf("%d%d",&n,&m);mx=n+m;
34 for(int i=1;i<=n;i++) scanf("%lld",&f[n-i+1].w),f[n-i+1].pos=n-i+1;
35 for(int i=1;i<=m;i++) scanf("%lld",&f[n+i].w),f[n+i].pos=n+i;
36 sort(f+1,f+n+m+1);ll tt=n;
37 for(int i=1;i<=mx;i++){
38 if(tt>=f[i].pos) ans+=tt-f[i].pos-(ask(tt)-ask(f[i].pos)),tt=f[i].pos;
39 else ans+=f[i].pos-tt-1-(ask(f[i].pos)-ask(tt)),tt=f[i].pos-1;
40 add(f[i].pos,1);
41 }
42 printf("%lld",ans);
43 return 0;
44 }