码迷,mamicode.com
首页 > 其他好文 > 详细

CDQ分治

时间:2019-02-15 15:59:49      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:def   数据   www   有一个   can   数组   sort   分时   数列   

首先,偏序是什么

一维偏序就是数列中对于每个\(x\)有多少个\(a\leq x\)

二维偏序就是二元组\((x,y)\)有多少\((a,b)\)满足\(a\leq x \wedge b\leq y\)

...

一维偏序可以直接排序

二维偏序联想到逆序对可以给第一位排序第二维数据结构

三维偏序第一维排序第二维cdq分治第三维树状数组

其实二维还有一个方法就是归并排序

每次二分时顺便统计左边对右边的影响

cdq分治就是这样

没了。。??


陌上花开

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define M 300001
using namespace std;

int n,m,k,a[M],c[M],cnt[M];
struct vv { int a,b,c,id,num,ans;} d[M],tmp[M];
bool cmp(vv a,vv b) 
{
    if(a.a!=b.a) return a.a<b.a;
    if(a.b!=b.b) return a.b<b.b;
    return a.c<b.c;
}

void add(int x,int k) { for(int i=x;i<=m;i+=i & -i) c[i]+=k;}
int ask(int x) { int ans=0; for(int i=x;i>0;i-=i & -i) ans+=c[i]; return ans;}

void cdq(int l,int r)
{
    if(l==r) return ;
    int mid=(l+r)>>1,cnt=0, j=l;
    cdq(l,mid); cdq(mid+1,r);
    for(int i=mid+1;i<=r;i++)
    {
        while(d[j].b<=d[i].b && j<=mid) add(d[j].c,d[j].num), tmp[cnt++]=d[j++];
        d[i].ans+=ask(d[i].c); tmp[cnt++]=d[i];  
    }
    for(int i=l;i<j;i++) add(d[i].c,-d[i].num);
    for(int i=mid;i>=j;i--) d[r+i-mid]=d[i]; 
    for(int i=0;i<cnt;i++) d[l+i]=tmp[i];
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&tmp[i].a,&tmp[i].b,&tmp[i].c), tmp[i].num=1;
    sort(tmp+1,tmp+1+n,cmp); 
    for(int i=1;i<=n;i++)
        if(tmp[i].a!=tmp[i-1].a || tmp[i].b!=tmp[i-1].b || tmp[i].c!=tmp[i-1].c) d[++k]=tmp[i], d[k].id=k;
        else d[k].num+=1;
    cdq(1,k); 
    for(int i=1;i<=k;i++) cnt[d[i].ans+d[i].num-1]+=d[i].num;
    for(int i=0;i<n;i++) printf("%d\n",cnt[i]);
}

CDQ分治

标签:def   数据   www   有一个   can   数组   sort   分时   数列   

原文地址:https://www.cnblogs.com/ZUTTER/p/10383590.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!