• P2163 [SHOI2007]园丁的烦恼


    题目

    P2163 [SHOI2007]园丁的烦恼

    做法

    关于拆点,要真想拆直接全部用树状数组水过不就好了

    做这题我们练一下(cdq)分治

    左下角((x1,y1))右上角((x2,y2)),查询(x1≤x≤x2)&&(y1≤y≤y2)的个数
    假设点(x,y)为矩形((x,y)(x,y))
    其实我们要查询的是(x1≤x,x2≥x,y1≤y≤y2)

    初始化排序(x)降序排,去掉(x1≤x),树状数组限制(x≤x2),区间查询(y1≤y≤y2),就是一三维偏序

    讲一下排序吧:
    由于我们要查询(x1≤x),所以初始化排序(x)降序排,(x1)我们就不管了
    升序排(x2)然后进树状数组,(y2)其实没用(区间查询就卡过去了)
    (y1≤y)由于这部分不好直接处理每个点结构体(y1=y)然后升序排
    最后由于重复点也要计算我们另点的(y2),由于查询的(y2)有值,(y2)升序排,让查询在前

    My complete code

    常数贼大的代码,还没某dalao不离散跑得快

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<string>
    #include<vector>
    using namespace std;
    typedef int LL;
    const LL maxn=2e6;
    inline LL Read(){
        LL x(0),f(1);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-'0',c=getchar();
        return x*f;
    }
    struct node{
        LL x1,y1,x2,y2,id,val;
    }a[maxn];
    LL n,m,tot1,tot2;
    LL tree[maxn],ans[maxn],x[maxn],y[maxn];
    inline bool cmp2(node g1,node g2){
        return g1.x2==g2.x2?(g1.y1==g2.y1?g1.y2<g2.y2:g1.y1>g2.y1):g1.x2<g2.x2;
    }
    inline bool cmp1(node g1,node g2){
        return (g1.x1^g2.x1)?g1.x1>g2.x1:cmp2(g1,g2);
    }
    inline LL Lowbit(LL x){
        return x&(-x);
    }
    inline void Add(LL x,LL val){
        for(;x<=tot2;x+=Lowbit(x))
            tree[x]+=val;
    }
    inline LL Query(LL x){
        LL ret(0);
        for(;x;x-=Lowbit(x))
            ret+=tree[x];
        return ret;
    }
    void Cdq(LL l,LL r){
        if(l==r)
            return;
        LL mid(l+r>>1);
        Cdq(l,mid),Cdq(mid+1,r),
        sort(a+l,a+1+mid,cmp2),sort(a+mid+1,a+1+r,cmp2);
        LL j(l-1);
        for(LL i=mid+1;i<=r;++i){
            while(j<mid&&a[j+1].x2<=a[i].x2)
                Add(a[j+1].y1,a[j+1].val),++j;
            ans[a[i].id]+=Query(a[i].y2)-Query(a[i].y1-1);
        }
        for(LL i=l;i<=j;++i)
            Add(a[i].y1,-a[i].val);
    }
    int main(){
        n=Read(),m=Read();
        for(LL i=1;i<=n;++i)
            x[++tot1]=a[i].x1=Read()+1,
            y[++tot2]=a[i].y1=Read()+1,
            a[i].val=1;
        for(LL i=1;i<=m;++i){
            LL now(n+i);
            x[++tot1]=a[now].x1=Read()+1,
            y[++tot2]=a[now].y1=Read()+1,
            x[++tot1]=a[now].x2=Read()+1,
            y[++tot2]=a[now].y2=Read()+1,
            a[now].id=i;
        }
        sort(x+1,x+1+tot1),sort(y+1,y+1+tot2),
        tot1=unique(x+1,x+1+tot1)-x-1,tot2=unique(y+1,y+1+tot2)-y-1;
        for(LL i=1;i<=n;++i)
            a[i].x2=a[i].x1=lower_bound(x+1,x+1+tot1,a[i].x1)-x,
            a[i].y1=lower_bound(y+1,y+1+tot2,a[i].y1)-y;
        for(LL i=1;i<=m;++i){
            LL now(n+i);
            a[now].x1=lower_bound(x+1,x+1+tot1,a[now].x1)-x,
            a[now].y1=lower_bound(y+1,y+1+tot2,a[now].y1)-y,
            a[now].x2=lower_bound(x+1,x+1+tot1,a[now].x2)-x,
            a[now].y2=lower_bound(y+1,y+1+tot2,a[now].y2)-y;
        }
        n+=m,
        sort(a+1,a+1+n,cmp1),
        Cdq(1,n);
        for(LL i=1;i<=m;++i)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
  • 相关阅读:
    Java 将Clob字段转换成String字符串
    Java BigDecimal详解
    java循环创建对象应该在循环体内还是循环体外
    Java 通过身份证获取生日和性别
    Java将数据进行分组处理
    Java 2进制和16进制的转换
    Map-HashMap 与 IF 判断内存占用对比
    Groovy脚本-通用SQL开关
    Oracle用户、授权、角色管理
    【docker随笔系列】安装sqlserver
  • 原文地址:https://www.cnblogs.com/y2823774827y/p/10285597.html
Copyright © 2020-2023  润新知