zoukankan      html  css  js  c++  java
  • [bzoj] 3295 动态逆序对 || CDQ分治

    原题

    给1到n的一个排列,按照某种顺序依次删除m个元素,求每删除一个元素之前统计整个序列的逆序对数。


    CDQ板题。因为删除不好处理,所以将其反过来,变为每次添加。每个数都赋予一个添加时间,每次”删除“操作后都是一次询问操作。
    三维分别为时间,位置,大小。
    某个元素加入后产生的贡献为时间更小、位置更小、数更大的个数 + 时间更小、位置更大、数更小的个数。

    #include<cstdio>
    #include<algorithm>
    #define N 1000010
    typedef long long ll;
    using namespace std;
    struct hhh
    {
        ll pos,w,tm;
        bool operator < (const hhh &b) const
    	{
    	    return tm<b.tm;
    	}
    }p[N];
    ll n,m,ans[N],f[N],x;
    
    bool cmp(hhh a,hhh b)
    {
        return a.w>b.w;
    }
    
    ll read()
    {
        ll ans=0,fu=1;
        char j=getchar();
        for (;j<'0' || j>'9';j=getchar()) if (j=='-') fu=-1;
        for (;j>='0' && j<='9';j=getchar()) ans*=10,ans+=j-'0';
        return ans*fu;
    }
    
    void add(int x,int y)
    {
        while (x<=n) f[x]+=y,x+=x&-x;
    }
    
    ll query(int x)
    {
        int ans=0;
        while (x) ans+=f[x],x-=x&-x;
        return ans;
    }
    
    void solve(int l,int r)
    {
        if (l==r) return ;
        int mid=(l+r)>>1;
        solve(l,mid);
        solve(mid+1,r);
        sort(p+l,p+mid+1,cmp);
        sort(p+mid+1,p+r+1,cmp);
        int ll=l,rr=mid+1;
        while (rr<=r)
        {
    	while (ll<=mid && p[ll].w>p[rr].w)
    	    add(p[ll].pos,1),ll++;
    	ans[p[rr].tm]+=query(p[rr].pos);
    	rr++;
        }
        while (--ll>=l) add(p[ll].pos,-1);//clear
        ll=mid;
        rr=r;
        while (rr>mid)
        {
    	while (ll>=l && p[ll].w<p[rr].w)
    	    add(p[ll].pos,1),ll--;
    	ans[p[rr].tm]+=query(n)-query(p[rr].pos);
    	rr--;
        }
        while (++ll<=mid) add(p[ll].pos,-1);
    }
    
    int main()
    {
        n=read();
        m=read();
        for (int i=1;i<=n;i++)
        {
    	x=read();
    	p[x].w=x;
    	p[x].pos=i;
        }
        for (int i=1;i<=m;i++)
        {
    	x=read();
    	p[x].tm=n-i+1;//插入时间,倒叙按插入处理
        }
        for (int i=1,cnt=1;i<=n;i++)
    	if (!p[i].tm) p[i].tm=cnt++;
        sort(p+1,p+n+1);
        solve(1,n);
        for (int i=2;i<=n;i++)
    	ans[i]+=ans[i-1];
        for (int i=n;i>n-m;i--)
    	printf("%lld
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    vue插件大全
    提高webpack的构建速度的几种方法概括
    当async/await碰见forEach-------------爆炸
    jquery 源码解析 节点遍历
    jquery工具类函数
    jqueryUI 插件
    Jquery常用插件
    jquery 基础-Ajax应用
    JavaScipt 源码解析 Sizzle选择器
    JavaScipt 源码解析 css选择器
  • 原文地址:https://www.cnblogs.com/mrha/p/8057728.html
Copyright © 2011-2022 走看看