BZOJ3192: [JLOI2013]删除物品(洛谷P3253)

292 篇文章 1 订阅
281 篇文章 1 订阅

树状数组

BZOJ题目传送门
洛谷题目传送门

一道很巧妙的题目所以我太菜根本想不到去看题解了

首先按什么顺序移动最优:当然是大的先移喽。
可以考虑两棵平衡树模拟,但是高级数据结构实在太烦,于是我们想用简单的方法。
我们把第一个序列倒过来,然后和第二个拼起来。这道题就变成按照大小顺序计算与中间的两个“堆顶”之间的距离。我们把有记为1,无记为0。那么其实就是询问区间和并且单点修改。树状数组维护即可。

代码:

#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
typedef long long LL;
int n,m,i,p,q,a[N],b[N],t[N],c[N];
F char readc(){
    static char buf[100000],*l=buf,*r=buf;
    if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
    if (l==r) return EOF; return *l++;
}
F int _read(){
    int x=0; char ch=readc();
    while (!isdigit(ch)) ch=readc();
    while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
    return x;
}
#define lbt(x) (x&(-x))
F void nsrt(int x,int p){ for (;x<=n;t[x]+=p,x+=lbt(x)); }
F int srch(int x){ for (i=0;x;i+=t[x],x-=lbt(x)); return i; }
int main(){
    n=_read(),m=_read(),p=n,q=n+1,n+=m;
    for (int i=p;i;i--) b[i]=a[i]=_read();
    for (int i=p+1;i<=n;i++) b[i]=a[i]=_read();
    sort(b+1,b+n+1); LL ans=0;
    for (int i=1;i<=n;i++)
        c[lower_bound(b+1,b+n+1,a[i])-b]=i;
    for (int i=1;i<=n;i++) nsrt(i,1);
    for (int i=n;i;i--){
        if (c[i]>p) ans+=srch(c[i]-1)-srch(p),nsrt(c[i],-1),p=c[i];
        else ans+=srch(p)-srch(c[i]),nsrt(c[i],-1),p=c[i];
    }
    return printf("%lld\n",ans),0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值