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]);
    }/*}}}*/
    
  • 相关阅读:
    软工实践寒假作业(1/2)
    java判断是否为数字
    前端测试工具Cypress
    StringBuffer&StringBuilder
    IO流
    kafka简介
    Python学习笔记10--unittest参数化
    python学习笔记9--日志模块logging
    Python学习笔记9-多线程和多进程
    python学习笔记9-单元测试unittest
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9318483.html
Copyright © 2011-2022 走看看