zoukankan      html  css  js  c++  java
  • CDQ 分治

    以前完全没有看过 CDQ 分治的东西。然后听说就是分治右区间,左区间然后计算左区间对右区间的贡献。然后上生物课的时候实在无聊然后随便yy了一下三维偏序,感觉不是很难(?

    首先要去重然后按第一维排序。然后每一个数要记录自己在原序列中出现了几次。cdq的时候考虑先分治左区间,分治右区间,然后再让左右区间分别按照第二维排序。由于我们已经保证右边的第一维一定大于左边的第一维,所以我们 two pointers+BIT 就可以算出对于右区间的每个元素,有多少个左区间的元素使得其第二维和第三维都比他小,

    洛谷模板P3810

    #include<bits/stdc++.h>
    #define int long long
    #define rep(i,a,b) for(register int i=(a);i<=(b);i++)
    #define per(i,a,b) for(register int i=(a);i>=(b);i--)
    using namespace std;
    const int N=4e5+9;
    
    inline int read() {
        register int x=0, f=1; register char c=getchar();
        while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
        return x*f;
    }
    
    int n,k,id[N],val[N],cnt,ans[N];
    struct node {int x,y,z,v,ans;} a[N];
    bool cmp(const node &x,const node &y) {
    	return x.x==y.x?(x.y==y.y?x.z<y.z:x.y<y.y):x.x<y.x;
    }
    bool operator == (const node &x,const node &y) {
    	return x.x==y.x&&x.y==y.y&&x.z==y.z;
    }
    bool cmpc(const node &x,const node &y) {
    	return x.y==y.y?x.z<y.z:x.y<y.y;
    }
    
    void uniq() {
    	sort(a+1,a+n+1,cmp);
    	rep(i,1,n) {
    		id[++cnt]=i, val[cnt]=1;
    		while(a[i+1]==a[i]) val[cnt]++, i++;
    	}
    	rep(i,1,cnt) a[i]=a[id[i]], a[i].v=val[i];
    }
    
    int s[N];
    int lb(int x) {return x&(-x);}
    void add(int x,int v) {for(;x<=k;x+=lb(x)) s[x]+=v;}
    int query(int x,int ret=0) {for(;x;x-=lb(x)) ret+=s[x]; return ret;}
    
    void cdq(int l,int r) {
    	if(l==r) return;
    	int mid=(l+r)/2;
    	cdq(l,mid), cdq(mid+1,r);
    	sort(a+l,a+mid+1,cmpc), sort(a+mid+1,a+r+1,cmpc);
    	int i=l,j=mid+1;
    	for(;j<=r;j++) {
    		while(a[i].y<=a[j].y&&i<=mid) add(a[i].z,a[i].v), i++;
    		a[j].ans+=query(a[j].z);
    	}
    	for(j=l;j<i;j++) add(a[j].z,-a[j].v);
    }
    
    signed main() {
    	n=read(), k=read();
    	rep(i,1,n) {
    		a[i].x=read(), a[i].y=read(), a[i].z=read();
    	}
    	uniq();
    	cdq(1,cnt);
    	rep(i,1,cnt) ans[a[i].ans+a[i].v-1]+=a[i].v;
    	rep(i,0,n-1) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    python
    python
    python
    python
    python
    python
    python
    python
    [ThinkPHP] 从一个表中获得栏目对应的ID,从另一个表获得属于这些栏目的文章
    [thinkPHP] buildSql可以查看tp CURD操作对应的SQL
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/14443410.html
Copyright © 2011-2022 走看看