Luogu P2448 无尽的生命

写在前面

这一篇没有什么好东西,为什么没人写Hash

Idea

因为本题求的是逆序对,重点是离散化,不是么?ts.png

于是可以用Hash来处理本题?

  • 裸的树状数组和归并有\(70\;pts\)裸的.png是吧

  • 根据这一篇题解,我们可以得到一种好的做法

这里我采用Hash

可以看看记录

jl.png

\(O2\)\(74\;ms\)悠闲.gif

Code

int Hash[maxn<<1],c[maxn<<1],l[maxn<<1];
int cnt,tot,n,m;
pair<int,int> p[maxn];
inline void add(int x,int v){
    for(int i=x;i<=m;i+=(-i)&i)
        c[i]+=v;
}
inline ll ask(int x){
    int ans=0;
    for(int i=x;i;i-=i&(-i))
        ans+=c[i];
    return ans;
}
signed main(){
    int k=read();
    for(int i=1;i<=k;i++){
        p[i].first=read(); p[i].second=read();
        Hash[++cnt]=p[i].first;
        Hash[++cnt]=p[i].second;//先都放入Hash数组里,之后排序去重
    }
    sort(Hash+1,Hash+cnt+1);
    m=unique(Hash+1,Hash+cnt+1)-Hash-1;
    for(int i=1;i<=m;i++) l[i]=i;//记录原始状态
    for(int i=1;i<=k;i++){
        int pos1=lower_bound(Hash+1,Hash+1+m,p[i].first)-Hash;
        int pos2=lower_bound(Hash+1,Hash+1+m,p[i].second)-Hash;
        swap(l[pos1],l[pos2]);//找到对应位置进行相应操作
    }
    ll ans=0;
    for(int i=m;i>=1;i--){
        ans+=ask(l[i]-1);//单点求逆序对
        add(l[i],1);//更新单点
        ll len=Hash[i]-Hash[i-1]-1;//求连续区间长度
        ans+=len*ask(i-1);//连续的不变区间,可以将它看作 i 这个数!
        if(i!=1) add(i-1,len);//最后一个不用更新了(也不能更新,会在更新中死循环,因为0的lowbit是0)
    }
    printf("%lld",ans);
    return 0;
}

\[ The \quad End \]

\[ \text{愿意用一支黑色的铅笔,画一出沉默舞台剧-《不要说话》陈奕迅} \]

转载于:https://www.cnblogs.com/cbyyc/p/11609547.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值