zoukankan      html  css  js  c++  java
  • 【bzoj3295】 Cqoi2011—动态逆序对

    http://www.lydsy.com/JudgeOnline/problem.php?id=3295 (题目链接)

    题意

      给出某种排列,按照某种顺序依次删除m个数,在每次删除一个数前统计序列中逆序对对个数。

    Solution

      作为一个CDQ分治的初学者,我毫不犹豫的%了LCF的题解。

      这里介绍下三维偏序的求法:一维排序,二维归并,三维树状数组。

      排序维护x维之后,递归处理:

        1.在处理区间[L,R]的时候,先二分区间[L, (L+R)/ 2],递归求这个左区间(二分的原因是我在维护y维的时候难免破坏x维的性质,但是二分之后我还是可以保证左区间的x全都大于右区间的x)。

        2.这个时候左区间y维已经有序,我们只好把右区间[(L+R)/2,R],快排一遍,进行归并式的dp转移(左区间一个指针,右区间一个指针,保证左区间指针所扫过的y一定小于右区间指针所扫过的y),然后在用常规的树状数组维护z。

        3.当然,最后还应该把右区间[(L+R)/2,R]按x快排回去,并递归处理这一段。

        4.最后归并或者快排维护整个区间的y有序。

      像这种题目,经常把时间作为第三维做三维偏序。

    细节

      ?

    代码

    // bzoj3295
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define inf (1ll<<60)
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
    using namespace std;
    
    const int maxn=100010;
    int c[maxn],f[maxn],pos[maxn],n,m;
    struct data {int x,y,z;}a[maxn],t[maxn];
    
    bool cmp(data a,data b) {
    	return a.z<b.z;
    }
    int lowbit(int x) {
    	return x&-x;
    }
    void add(int x,int val) {
    	for (int i=x;i<=n;i+=lowbit(i)) c[i]+=val;
    }
    LL query(int x) {
    	int res=0;
    	for (int i=x;i;i-=lowbit(i)) res+=c[i];
    	return res;
    }
    void solve(int l,int r) {
    	if (l==r) return;
    	int mid=(l+r)>>1;
    	solve(l,mid);solve(mid+1,r);
    	for (int i=l,j=mid+1,k=l;i<=mid || j<=r;) {
    		if ((j<=r && a[j].x<a[i].x) || i>mid) add(a[j].y,1),t[k++]=a[j++];
    		else f[a[i].z]+=query(n)-query(a[i].y),t[k++]=a[i++];
    	}
    	for (int i=mid+1;i<=r;i++) add(a[i].y,-1);
    	for (int i=mid,j=r;i>=l || j>=mid+1;) {
    		if ((j>=mid+1 && a[j].x>a[i].x) || i<l) add(a[j].y,1),j--;
    		else f[a[i].z]+=query(a[i].y-1),i--;
    	}
    	for (int i=mid+1;i<=r;i++) add(a[i].y,-1);
    	for (int i=l;i<=r;i++) a[i]=t[i];
    }
    int main() {
    	scanf("%d%d",&n,&m);
    	for (int x,i=1;i<=n;i++) scanf("%d",&x),pos[x]=i;
    	for (int x,i=1;i<=m;i++) scanf("%d",&x),a[pos[x]]=(data){x,pos[x],i};
    	for (int x=m,i=1;i<=n;i++) if (!a[pos[i]].z) a[pos[i]]=(data){i,pos[i],++x};
    	sort(a+1,a+1+n,cmp);
    	solve(1,n);
    	LL ans=0;
    	for (int i=1;i<=n;i++) ans+=f[i];
    	for (int i=1;i<=m;i++) printf("%lld
    ",ans),ans-=f[i];
    	return 0;
    }
    
  • 相关阅读:
    【今日CV 视觉论文速览】 19 Nov 2018
    【numpy求和】numpy.sum()求和
    【今日CV 视觉论文速览】16 Nov 2018
    【今日CV 视觉论文速览】15 Nov 2018
    poj 2454 Jersey Politics 随机化
    poj 3318 Matrix Multiplication 随机化算法
    hdu 3400 Line belt 三分法
    poj 3301 Texas Trip 三分法
    poj 2976 Dropping tests 0/1分数规划
    poj 3440 Coin Toss 概率问题
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/6001078.html
Copyright © 2011-2022 走看看