• P3810 【模板】三维偏序(陌上花开)(CDQ分治)


    jisoo

    典型的CDQ分治

    一维的时候比较就行了

    二维的时候加一个数据结构,就像逆序对一样

    三维的时候则需要,使用CDQ分治来解决了

    首先把全局按照第一维从小到大排序,相同的按照第二维,还相同的按照第三维

    然后开始从中间分开,分治。

    显然这个过程位于 (mid) 两边内部的都会在自己的过程中被解决,新的贡献来自于跨过mid的比较。

    这一部分怎么处理呢?首先两边都按照第二维排序。按照类似于归并的方式每一部分进行一个指针,把前面的和后面的部分比较第二维,并且把第二维小于后半部分的前半部分的元素扔到一个树状数组里(处理第三位)

    这样我们就找到了第一维,第二维都小于后面元素的元素,再按照类似于求逆序对的思想,用树状数组查询其中第三维也比他小的元素的数量

    搞定

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    template<class T>inline void read(T &x)
    {
        x=0;register char c=getchar();register bool f=0;
        while(!isdigit(c))f^=c=='-',c=getchar();
        while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
        if(f)x=-x;
    }
    template<class T>inline void print(T x)
    {
        if(x<0)putchar('-'),x=-x;
        if(x>9)print(x/10);
        putchar('0'+x%10);
    }
    const int maxn=200005;
    struct e{
    	int x;
    	int y;
    	int c;
    	int num;
    	int ans;
    }el[maxn],e2[maxn];
    bool cmp1(e x,e y){
    	if(x.x==y.x) return x.y==y.y?x.c<y.c:x.y<y.y;
    	else return x.x<y.x;
    }
    bool cmp2(e x,e y){
    	return x.y==y.y?x.c<y.c:x.y<y.y;
    }
    int cnt;
    int n,k;
    int tr[maxn];
    int lowbit(int x){
    	return x&-x;
    }
    void add(int x,int kk){
    	for(int i=x;i<=k;i+=lowbit(i)){
    		tr[i]+=kk;
    	}
    }
    int qu(int x){
    	int ans=0;
    	while(x){
    		ans+=tr[x];
    		x-=lowbit(x);
    	}
    	return ans;
    }
    int x,y,z;
    long long ans[maxn];
    void cdq(int l,int r){
    	if(l==r) return ;
    	int mid=(l+r)>>1;
    	cdq(l,mid);cdq(mid+1,r);
    	sort(e2+l,e2+mid+1,cmp2);
    	sort(e2+mid+1,e2+r+1,cmp2);
    	int ll=l;
    	for(int rr=mid+1;rr<=r;++rr){
    		while(e2[rr].y>=e2[ll].y&&ll<=mid){
    			add(e2[ll].c,e2[ll].num);
    			ll++;
    		}
    		e2[rr].ans+=qu(e2[rr].c);
    	}
    	for(int i=l;i<ll;++i){
    		add(e2[i].c,-e2[i].num);
    	}
    }
    int main(){
    	read(n);read(k);
    	for(int i=1;i<=n;++i){
    		read(el[i].x);read(el[i].y);read(el[i].c);
    	}
    	sort(el+1,el+n+1,cmp1);
    	for(int i=1;i<=n;++i){
    		if(el[i].x!=el[i-1].x||el[i].y!=el[i-1].y||el[i].c!=el[i-1].c){
    			cnt++;
    			e2[cnt].x=el[i].x;
    			e2[cnt].y=el[i].y;
    			e2[cnt].c=el[i].c;
    			e2[cnt].num=1;
    		}else{
    			e2[cnt].num++;
    		}
    	}
    	cdq(1,cnt);
    	for(int i=1;i<=cnt;++i){
    		ans[e2[i].ans+e2[i].num-1]+=e2[i].num;
    	}
    	for(int i=0;i<n;++i){
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    集合类的相关之区别
    String,实例,变量
    Java集合类详解
    英语飙升的好方法[网上转来的]
    jstl标签常用标签(全)
    Android 菜单(OptionMenu)大全 建立你自己的菜单
    持久层封装 JDBC
    SQL Sever 常用语句总结
    异常:数据库没有有效所有者,因此无法安装数据库关系图支持对象
    Log4j配置详解
  • 原文地址:https://www.cnblogs.com/For-Miku/p/15498314.html
Copyright © 2020-2023  润新知