zoukankan      html  css  js  c++  java
  • CDQ分治模板题

    P3810 三维偏序(陌上花开)

    CDQ分治模板题
    第一维直接排序,第二维用分治,第三维用树状数组

    #include<bits/stdc++.h>
    using namespace std;
    const int maxx = 1e5+10;
    struct node
    {
        int a,b,c,w,s;
    }e[maxx],g[maxx];
    bool cmp(node x,node y)
    {
        if(x.a!=y.a)return x.a<y.a;
        if(x.b!=y.b)return x.b<y.b;
        return x.c<y.c;
    }
    int t[2*maxx],ans[maxx];
    int n,m;
    void add(int x,int c)
    {
        for(int i=x;i<=m;i+=(i&(-i)))t[i]+=c;
    }
    int getsum(int x)
    {
        int res=0;
        for(int i=x;i>0;i-=(i&(-i)))res+=t[i];
        return res;
    }
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=(l+r)/2;
        cdq(l,mid);cdq(mid+1,r);
        int p=l,q=mid+1,cnt=l;
        while(p<=mid&&q<=r)
        {
            if(e[p].b<=e[q].b)add(e[p].c,e[p].w),g[cnt++]=e[p++];
            else e[q].s+=getsum(e[q].c),g[cnt++]=e[q++];
        }
        while(p<=mid)add(e[p].c,e[p].w),g[cnt++]=e[p++];
        while(q<=r)e[q].s+=getsum(e[q].c),g[cnt++]=e[q++];
        for(int i=l;i<=mid;i++)add(e[i].c,-e[i].w);
        for(int i=l;i<=r;i++)e[i]=g[i];
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].c);
            e[i].w=1;
        }
        sort(e+1,e+1+n,cmp);
        int tot=1;
        for(int i=2;i<=n;i++)
        {
            if(e[i].a==e[tot].a&&e[i].b==e[tot].b&&e[i].c==e[tot].c)e[tot].w++;
            else e[++tot]=e[i];
        }
        cdq(1,tot);
        for(int i=1;i<=tot;i++)ans[e[i].s+e[i].w-1]+=e[i].w;
        for(int i=0;i<n;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    

    2018SEERC Points and Rectangles(洛谷P5873)

    题意:
    二维平面上,两种操作:
    1 x y:在(x,y)放一个点
    2 x1,y1,x2,y2:放一个左下角为(x1,y1),右上角为(x2,y2)的矩阵。
    每次操作之后要求出 所有矩阵包含的点的数目 的总和。

    第一维为操作顺序,第二维为x,第三维为y
    分别统计点和矩阵的相互贡献。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxx = 4e5+10;
    struct node
    {
        int op,x,y,id;
        bool operator < (const node &t)const
        {
            return id<t.id;
        }
    }e[maxx],g[maxx];
    int a[maxx],t[maxx],ans[maxx];
    int tot=0,num=0;
    vector<int>v1,v2;
    void add(int x,int c)
    {
        for(int i=x;i<=num;i+=(i&(-i)))t[i]+=c;
    }
    int getsum(int x)
    {
        int res=0;
        for(int i=x;i>0;i-=(i&(-i)))res+=t[i];
        return res;
    }
    void cdq1(int l,int r) //点对矩阵贡献
    {
        if(l==r)return;
        int mid=(l+r)/2;
        cdq1(l,mid),cdq1(mid+1,r);
        int p=l,q=mid+1,cnt=l;
        while(p<=mid&&q<=r)
        {
            if(e[p].x<=e[q].x)
            {
                if(e[p].op==1)add(e[p].y,1),v1.push_back(e[p].y);
                g[cnt++]=e[p++];
            }
            else
            {
                if(e[q].op==2)ans[e[q].id]+=getsum(e[q].y);
                else if(e[q].op==3)ans[e[q].id]-=getsum(e[q].y);
                g[cnt++]=e[q++];
            }
        }
        while(p<=mid)g[cnt++]=e[p++];
        while(q<=r)
        {
            if(e[q].op==2)ans[e[q].id]+=getsum(e[q].y);
            else if(e[q].op==3)ans[e[q].id]-=getsum(e[q].y);
            g[cnt++]=e[q++];
        }
        for(int i=l;i<=r;i++)e[i]=g[i];
        for(int i=0;i<v1.size();i++)add(v1[i],-1);
        v1.clear();
    }
    //(x1-1,y1-1),(x1-1,y2),(x2,y1-1),(x2,y2)对应贡献为1,-1,-1,1
    void cdq2(int l,int r) //矩阵对点贡献
    {
        if(l==r)return;
        int mid=(l+r)/2;
        cdq2(l,mid),cdq2(mid+1,r);
        int p=l,q=mid+1,cnt=l;
        while(p<=mid&&q<=r)
        {
            if(e[p].x<e[q].x)
            {
                if(e[p].op==2)add(e[p].y,1),v1.push_back(e[p].y);
                else if(e[p].op==3)add(e[p].y,-1),v2.push_back(e[p].y);
                g[cnt++]=e[p++];
            }
            else
            {
                if(e[q].op==1)ans[e[q].id]+=getsum(e[q].y-1);  //注意这里要减1
                g[cnt++]=e[q++];
            }
        }
        while(p<=mid)g[cnt++]=e[p++];
        while(q<=r)
        {
            if(e[q].op==1)ans[e[q].id]+=getsum(e[q].y-1);
            g[cnt++]=e[q++];
        }
        for(int i=l;i<=r;i++)e[i]=g[i];
        for(int i=0;i<v1.size();i++)add(v1[i],-1);
        for(int i=0;i<v2.size();i++)add(v2[i],1);
        v1.clear(),v2.clear();
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        int op,x1,y1,x2,y2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&x1,&y1);
                e[++tot]=node{op,x1,y1,i};
                a[++num]=x1,a[++num]=y1;
            }
            else
            {
                scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
                e[++tot]=node{op,x1-1,y1-1,i};
                e[++tot]=node{op,x2,y2,i};
                e[++tot]=node{op+1,x1-1,y2,i};
                e[++tot]=node{op+1,x2,y1-1,i};
                a[++num]=x1-1,a[++num]=y1-1,a[++num]=x2,a[++num]=y2;
            }
        }
        sort(a+1,a+1+num);
        num=unique(a+1,a+1+num)-a-1;
        for(int i=1;i<=tot;i++)
        {
            e[i].x=lower_bound(a+1,a+1+num,e[i].x)-a;
            e[i].y=lower_bound(a+1,a+1+num,e[i].y)-a;
        }
        cdq1(1,tot);
        sort(e+1,e+1+tot);
        cdq2(1,tot);
        LL res=0;
        for(int i=1;i<=n;i++)
        {
            res+=ans[i];
            printf("%lld
    ",res);
        }
        return 0;
    }
    
  • 相关阅读:
    面向对象、面向接口、面向方法编程的区别?
    面向接口、对象、方面编程区别 -- 精简版
    面向接口编程详解(一)——思想基础
    吴裕雄--天生自然数据结构:静态链表及其创建
    吴裕雄--天生自然数据结构:单链表的基本操作
    吴裕雄--天生自然数据结构:单链表,链式存储结构
    吴裕雄--天生自然数据结构:顺序表的基本操作
    吴裕雄--天生自然Python Matplotlib库学习笔记:matplotlib绘图(2)
    吴裕雄--天生自然Python Matplotlib库学习笔记:matplotlib绘图(1)
    吴裕雄--天生自然Numpy库学习笔记:NumPy Matplotlib
  • 原文地址:https://www.cnblogs.com/HooYing/p/12459709.html
Copyright © 2011-2022 走看看