动态逆序对1

7 篇文章 0 订阅
5 篇文章 0 订阅

前言

容易写挂(对于新手与蒟蒻)

题面

洛谷;

sol

CDQ
如果按照三维偏序那样求,那么会漏掉一些情况。所以要跑两遍cdq。
两遍CDQ又会有一个问题,就是判等于的问题。第一遍CDQ第三维判等于,第二遍判不等于.

code

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int lowbit(int k){return (-k)&k;}
namespace zjy_io{
    inline char gc(){
        static char buf[1<<6],*p1=buf,*p2=buf;
        return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,1<<6,stdin),p1==p2)?EOF:*p1++;
    }
    template <class T>
    inline void read(T&data){
        data=0;
        register char ch=0;
        register int caa=1;
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=gc();
        ch=='-'?caa=-1,ch=gc():caa=1;
        while(ch<='9'&&ch>='0'){
            data=(data<<3)+(data<<1)+(ch^48);
            ch=gc();
        }
        data*=caa;
    }
    inline char Getchar(){
        register char ch=0;
        while(ch<'A'||ch>'Z')ch=gc();return ch;
    }
    inline void write(LL x){
        if(x>9)write(x/10);
        putchar(x%10+'0');
    }
}
using namespace zjy_io;
const int _ = 1.03e5;

int n,m,cnt;
struct node{
    int a,b,c;
}s[_],q[_];
int num[_];//ai<aj,bi>bj,ci<cj,
LL ans[_];
LL tree[_];
struct er{
    int a,b;
}rr[_];
inline void modify(register int loc,register int zh){
    for(register int i=loc;i<=n;i+=lowbit(i))tree[i]+=zh;
}
inline int query(register int loc){
    register int ret1=0,ret2=0;
    for(register int i=loc-1;i;i-=lowbit(i))ret1+=tree[i];
    for(register int i=n;i;i-=lowbit(i))ret2+=tree[i];
    return ret2-ret1;
}
bool cmp(node x,node y){
    return x.a<y.a;
}
void CDQ1(register int L,register int R){
    if(L==R)return;
    register int mid=(L+R)>>1;
    CDQ1(L,mid);CDQ1(mid+1,R);
    register int pin1=mid,pin2=R,ppl=R;
    for(;pin2>=mid+1;pin2--){
        while(s[pin1].b>s[pin2].b&&pin1>=L){
            q[ppl]=s[pin1];
            rr[++cnt]=(er){s[pin1].c,1};
            modify(s[pin1].c,1);--ppl,--pin1;
        }
        ans[s[pin2].c]+=query(s[pin2].c+1);
        //cout<<L<<' '<<R<<' '<<s[pin2].a<<' '<<ans[s[pin2].c]<<endl;
        q[ppl]=s[pin2];ppl--;
    }
    while(pin1>=L){q[ppl]=s[pin1];--ppl,--pin1;}
    for(register int i=L;i<=R;++i)s[i]=q[i];
    for(register int i=1;i<=cnt;++i)modify(rr[i].a,-rr[i].b);cnt=0;
}
void CDQ(register int L,register int R){
    if(L==R)return;
    register int mid=(L+R)>>1;
    CDQ(L,mid),CDQ(mid+1,R);
    register int pin1=L,pin2=mid+1,ppl=L;
    for(;pin1<=mid;pin1++){
        while(s[pin1].b>s[pin2].b&&pin2<=R){
            q[ppl]=s[pin2];
            rr[++cnt]=(er){s[pin2].c,1};
            modify(s[pin2].c,1),++ppl,++pin2;
        }
        ans[s[pin1].c]+=query(s[pin1].c),q[ppl]=s[pin1],ppl++;
    }
    while(pin2<=R)q[ppl]=s[pin2],++ppl,++pin2;
    for(register int i=L;i<=R;++i)s[i]=q[i];
    for(register int i=1;i<=cnt;++i)modify(rr[i].a,-rr[i].b);cnt=0;
}
int main(){
    read(n),read(m);
    for(register int i=1;i<=n;++i)
        read(s[i].a),s[i].b=i,num[s[i].a]=i;
    register int h;
    for(register int i=1;i<=m;++i)
        read(h),s[num[h]].c=i;
    for(register int i=1;i<=n;++i)
        if(!s[i].c)s[i].c=m+1;
    sort(s+1,s+n+1,cmp);
    CDQ(1,n);
    sort(s+1,s+n+1,cmp);
    for(register int i=m+1;i>=1;--i)
        ans[i]=ans[i]+ans[i+1];
    for(register int i=1;i<=m;++i)
        write(ans[i]),puts("");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值