CDQ(動態逆序對的幾種做法)
阿新 • • 發佈:2018-06-02
DC pair c++ first getchar() ID 數據結構 tchar n)
菜雞總覺得自己會了很多東西 然而在學長的鞭策下 還有很多需要加深的 希望再一次突破自己的數據結構!
#include <bits/stdc++.h> #define f first #define s second #define ll long long #define pii pair<ll,int> #define inc(i,l,r) for(int i=l;i<=r;i++) const int MAXN=1e5+10; using namespace std; ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar(); return f*x; } int a[MAXN];int b[MAXN],c[MAXN]; int G[MAXN]; ll ans[MAXN];ll d[MAXN]; int n,m; int get_id(int x){return x&(-x);} ll Sum(int x){ ll sum=0; for(int i=x;i>0;i-=get_id(i))sum+=d[i]; return sum; } void update(int x,int vul){ for(int i=x;i<=m+1;i+=get_id(i))d[i]+=vul; } void update1(int x,int vul){ for(int i=x;i<=n;i+=get_id(i))d[i]+=vul; } void clean(int x){ for(int i=x;i<=m+1;i+=get_id(i))d[i]=0; } void querty(int l,int r,int mid){ int i=l,j=mid+1;G[0]=0; while(i<=mid&&j<=r){ while(i<=mid&&c[i]<c[j]){ G[++G[0]]=c[i]; update(b[c[i]],1);i++; } ans[b[c[j]]]+=Sum(m+1)-Sum(b[c[j]]); G[++G[0]]=c[j]; j++; } if(i<=mid){ for(;i<=mid;i++)G[++G[0]]=c[i]; } if(j<=r){ for(;j<=r;j++){ ans[b[c[j]]]+=Sum(m+1)-Sum(b[c[j]]); G[++G[0]]=c[j]; } } for(int i=1;i<=G[0];i++)c[l+i-1]=G[i],clean(b[G[i]]); } void cdq(int l,int r){ if(l>=r)return ; int mid=(l+r)>>1; cdq(l,mid); cdq(mid+1,r); querty(l,r,mid); } void querty1(int l,int r,int mid){ int i=l,j=mid+1;G[0]=0; while(i<=mid&&j<=r){ while(i<=mid&&a[i]>a[j]){ G[++G[0]]=a[i]; update(b[a[i]],1);i++; } ans[b[a[j]]]+=Sum(m+1)-Sum(b[a[j]]); G[++G[0]]=a[j]; j++; } if(i<=mid){ for(;i<=mid;i++)G[++G[0]]=a[i]; } if(j<=r){ for(;j<=r;j++){ ans[b[a[j]]]+=Sum(m+1)-Sum(b[a[j]]); G[++G[0]]=a[j]; } } for(int i=1;i<=G[0];i++)a[l+i-1]=G[i],clean(b[G[i]]); } void cdq1(int l,int r){ if(l>=r)return ; int mid=(l+r)>>1; cdq1(l,mid); cdq1(mid+1,r); querty1(l,r,mid); } int main(){ n=read();m=read(); inc(i,1,n)a[i]=read(),c[n-i+1]=a[i]; int vul; inc(i,1,m)vul=read(),b[vul]=i; inc(i,1,n)if(!b[i])b[i]=m+1; ll sum=0; for(int i=1;i<=n;i++){ sum+=(Sum(n)-Sum(a[i])); update1(a[i],1); } for(int i=1;i<=n;i++)clean(a[i]); cdq(1,n); cdq1(1,n); printf("%lld\n",sum); for(int i=1;i<m;i++)sum-=ans[i],printf("%lld\n",sum); return 0; }
CDQ(動態逆序對的幾種做法)