• 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 ]

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

  • 相关阅读:
    java实现RSA非对称加密
    lombok中的@Builder注解
    java实现大文件的分割与合并
    IDEA新建springboot选择DevTools
    bat命令自动配置java环境变量
    java实现发送邮件
    随记
    编译原理学习——FIRST和LASTVT
    国王的游戏
    JAVA类加载及NEW对象的过程
  • 原文地址:https://www.cnblogs.com/cbyyc/p/11609547.html
Copyright © 2020-2023  润新知