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

    Portal --> bzoj3295

    Solution

      虽然说这个可能原本是一道愉快的树套树但是

    ​  没有强制在线并且是三维限制那就大力cdq分治啊!

      

    ​  看到“按照某个顺序依次删除”这样的字眼,比较容易联想到一个套路:反过来看,变成按照某个顺序依次插入

    ​  那么对于一个询问,删掉它之前(转化完了之后就是插入它之后)的所会影响到的逆序对数可以分为两种:一种是在它前面但是比它大的,一种是在它后面但是比它小的

    ​  对于每一个转化后的插入我们都计算出这样两个值的和,然后答案显然就是累加一下就好了

    ​  所以我们按照位置递增做一次cdq,然后再按照位置递减做一次cdq,就可以将上面两种情况分别算出来了

      总的来说就是:时间维用排序,位置维用cdq,数值维用树状数组,然后就很愉快滴做完了

    ​  注意因为一开始的时候我们将顺序反了过来所以最后要反着输出

      

      代码大概长这个样子:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=100010;
    struct Op{
    	int pos,val,t;
    	friend bool operator < (Op x,Op y)
    	{return x.t<y.t;}
    }a[N],rec[N];
    int lis[N],pos[N];
    ll c[N],ans[N];
    int n,m,tot,mx;
    
    void insert(int x,int delta){
    	for (;x;x-=x&-x) c[x]+=delta;
    }
    int query(int x){
    	int ret=0;
    	for (;x<=mx;x+=x&-x) ret+=c[x];
    	return ret;
    }
    void solve(int l,int r){
    	if (l==r) return;
    	int mid=l+r>>1;
    	solve(l,mid);
    	solve(mid+1,r);
    	int tmp,tp=l,tot=l-1;
    	for (int i=mid+1;i<=r;++i){
    		while (tp<=mid&&a[tp].pos<a[i].pos)
    			rec[++tot]=a[tp],insert(a[tp++].val,1);
    		rec[++tot]=a[i];
    		ans[a[i].t]+=query(a[i].val+1);
    	}
    	for (int i=l;i<tp;++i) insert(a[i].val,-1);
    	for (int i=tp;i<=mid;++i) rec[++tot]=a[i];
    	for (int i=l;i<=r;++i) a[i]=rec[i];
    }
    
    int main(){/*{{{*/
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	int x;
    	scanf("%d%d",&n,&m);
    	mx=0;
    	for (int i=1;i<=n;++i) 
    		scanf("%d",&a[i].val),a[i].pos=i,pos[a[i].val]=i,mx=max(mx,a[i].val);
    	for (int i=1;i<=m;++i){
    		scanf("%d",&x);
    		a[pos[x]].t=m-i+1;
    	}
    	sort(a+1,a+1+n);
    	solve(1,n);
    	for (int i=1;i<=n;++i) 
    		a[i].pos*=-1,a[i].val=n-a[i].val+1;
    	sort(a+1,a+1+n);
    	solve(1,n);
    	for (int i=1;i<=m;++i) ans[i]+=ans[i-1];
    	for (int i=1;i<=m;++i)
    		printf("%lld
    ",ans[m-i+1]);
    }/*}}}*/
    
  • 相关阅读:
    Oracle PL/SQL攻略
    Android数据库中查找一条数据 query方法详解
    验证视图MAC失败 Validation of ViewState MAC Failed
    长方体类
    用类的友元函数完成运算符的重载
    全国软件2. 三人年龄
    Android中实现带声音提示的Toast (自定义扩展Toast)
    js判断生效时间不得大于失效时间
    OpenGL运用辅助库创建规则几何对象
    Ubuntu13.04安装CUDA5.0
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9318483.html
Copyright © 2011-2022 走看看