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 }

 

posted @ 2018-04-17 14:25  Jack_the_Ripper  阅读(102)  评论(0编辑  收藏  举报