zoukankan      html  css  js  c++  java
  • 初涉二维数点问题&&bzoj1935: [Shoi2007]Tree 园丁的烦恼

     离线好评

    Description

    很久很久以前,在遥远的大陆上有一个美丽的国家。统治着这个美丽国家的国王是一个园艺爱好者,在他的皇家花园里种植着各种奇花异草。有一天国王漫步在花园里,若有所思,他问一个园丁道: “最近我在思索一个问题,如果我们把花坛摆成六个六角形,那么……” “那么本质上它是一个深度优先搜索,陛下”,园丁深深地向国王鞠了一躬。 “嗯……我听说有一种怪物叫九头蛇,它非常贪吃苹果树……” “是的,显然这是一道经典的动态规划题,早在N元4002年我们就已经发现了其中的奥秘了,陛下”。 “该死的,你究竟是什么来头?” “陛下息怒,干我们的这行经常莫名其妙地被问到和OI有关的题目,我也是为了预防万一啊!” 王者的尊严受到了伤害,这是不可容忍的。看来一般的难题是难不倒这位园丁的,国王最后打算用车轮战来消耗他的实力: “年轻人,在我的花园里的每一棵树可以用一个整数坐标来表示,一会儿,我的骑士们会来轮番询问你某一个矩阵内有多少树,如果你不能立即答对,你就准备走人吧!”说完,国王气呼呼地先走了。 这下轮到园丁傻眼了,他没有准备过这样的问题。所幸的是,作为“全国园丁保护联盟”的会长——你,可以成为他的最后一根救命稻草。

    Input

    第一行有两个整数n,m(0≤n≤500000,1≤m≤500000)。n代表皇家花园的树木的总数,m代表骑士们询问的次数。 文件接下来的n行,每行都有两个整数xi,yi,代表第i棵树的坐标(0≤xi,yi≤10000000)。 文件的最后m行,每行都有四个整数aj,bj,cj,dj,表示第j次询问,其中所问的矩形以(aj,bj)为左下坐标,以(cj,dj)为右上坐标。

    Output

    共输出m行,每行一个整数,即回答国王以(aj,bj)和(cj,dj)为界的矩形里有多少棵树。

    题目分析

    这就是一个经典的二维数点问题。
    于是这里提供两种做法:
    1.树状数组离散化
    2.cdq分治
     
    这里是BIT做法:
     1 #include<bits/stdc++.h>
     2 const int maxn = 500013;
     3 
     4 struct node
     5 {
     6     int x,y,lb,fr;
     7     bool operator < (node a) const
     8     {
     9         return x==a.x?lb<a.lb:x<a.x;
    10     }
    11 }f[5*maxn];
    12 int n,m,cnt,tot;
    13 int sum[maxn],ans[maxn][5];
    14 int a[maxn],b[maxn],c[maxn],d[maxn],x[maxn],y[maxn],p[5*maxn];
    15 
    16 int lowbit(int x){return x&-x;}
    17 void add(int x){for (; x<=cnt; x+=lowbit(x)) sum[x]++;}
    18 int query(int x)
    19 {
    20     int ret = 0;
    21     for (; x; x-=lowbit(x))
    22         ret += sum[x];
    23     return ret;
    24 }
    25 int read()
    26 {
    27     char ch = getchar();
    28     int num = 0;
    29     for (; !isdigit(ch); ch = getchar());
    30     for (; isdigit(ch); ch = getchar())
    31         num = (num<<1)+(num<<3)+ch-48;
    32     return num;
    33 }
    34 int main()
    35 {
    36     n = read(), m = read();
    37     for (int i=1; i<=n; i++)
    38         x[i] = read()+1, y[i] = read()+1, p[++cnt] = y[i];
    39     for (int i=1; i<=m; i++)
    40         a[i] = read()+1, b[i] = read()+1, c[i] = read()+1, d[i] = read()+1,
    41         p[++cnt] = b[i], p[++cnt] = d[i];
    42     std::sort(p+1, p+cnt+1);
    43     cnt = std::unique(p+1, p+cnt+1)-p-1;
    44     for (int i=1; i<=n; i++)
    45         y[i] = std::lower_bound(p+1, p+cnt+1, y[i])-p,
    46         f[++tot].x = x[i], f[tot].y = y[i];
    47     for (int i=1; i<=m; i++)
    48     {
    49         b[i] = std::lower_bound(p+1, p+cnt+1, b[i])-p;
    50         d[i] = std::lower_bound(p+1, p+cnt+1, d[i])-p;
    51         f[++tot].x = a[i]-1, f[tot].y = b[i]-1, f[tot].lb = 1,f[tot].fr = i;
    52         f[++tot].x = a[i]-1, f[tot].y = d[i], f[tot].lb = 2,f[tot].fr = i;
    53         f[++tot].x = c[i], f[tot].y = b[i]-1, f[tot].lb = 3,f[tot].fr = i;
    54         f[++tot].x = c[i], f[tot].y = d[i], f[tot].lb = 4,f[tot].fr = i;
    55     }
    56     std::sort(f+1, f+1+tot);
    57     for (int i=1; i<=tot; i++)
    58         if (f[i].lb) ans[f[i].fr][f[i].lb] = query(f[i].y);
    59         else add(f[i].y);
    60     for (int i=1; i<=m; i++)
    61         printf("%d
    ",ans[i][4]+ans[i][1]-ans[i][2]-ans[i][3]);
    62     return 0;
    63 }

    这里是cdq做法:

     1 #include<bits/stdc++.h>
     2 const int maxn = 500013;
     3 const int maxk = 10000033;
     4 
     5 struct point
     6 {
     7     int x,y,lb,mt;
     8     point() {}
     9     point(int a, int b, int c, int d):x(a),y(b),lb(c),mt(d) {}
    10     bool operator < (point a) const
    11     {
    12         return x==a.x?abs(mt) < abs(a.mt):x < a.x;
    13     }
    14 }f[maxn*5],s[maxn*5];
    15 int n,m,cnt,dfn,maxy;
    16 int sum[maxk],tim[maxk],ans[maxn];
    17 
    18 int lowbit(int x){return x&-x;}
    19 void add(int x)
    20 {
    21     for (; x <= maxy; x += lowbit(x))
    22     {
    23         if (tim[x] != dfn) tim[x] = dfn, sum[x] = 0;
    24         sum[x]++;
    25     }
    26 }
    27 int query(int x)
    28 {
    29     int ret = 0;
    30     for (; x; x -= lowbit(x))
    31         if (tim[x] == dfn)
    32             ret += sum[x];
    33     return ret;
    34 }
    35 int read()
    36 {
    37     char ch = getchar();
    38     int num = 0;
    39     for (; !isdigit(ch); ch = getchar());
    40     for (; isdigit(ch); ch = getchar())
    41         num = (num<<1)+(num<<3)+ch-48;
    42     return num;
    43 }
    44 void cdq(int l, int r)
    45 {
    46     if (l >= r) return;
    47     int mid = (l+r)>>1, L = l, R = mid+1, now = l;
    48     cdq(l, mid);
    49     cdq(mid+1, r);
    50     dfn++;
    51     while (L <= mid && R <= r)
    52         if (f[L] < f[R]){
    53             if (!f[L].mt) add(f[L].y);
    54             s[now++] = f[L++];
    55         }else{
    56             if (f[R].mt) ans[f[R].lb] += f[R].mt*query(f[R].y);
    57             s[now++] = f[R++];
    58         }
    59     while (L <= mid) s[now++] = f[L++];
    60     while (R <= r)
    61     {
    62         if (f[R].mt) ans[f[R].lb] += f[R].mt*query(f[R].y);
    63         s[now++] = f[R++];
    64     }
    65     for (int i=l; i<=r; i++) f[i] = s[i];
    66 }
    67 int main()
    68 {
    69     n = read(), m = read();
    70     for (int i=1; i<=n; i++)
    71         f[++cnt].x = read()+1, f[cnt].y = read()+1, maxy = std::max(maxy, f[cnt].y);
    72     for (int i=1; i<=m; i++)
    73     {
    74         int a = read()+1, b = read()+1, c = read()+1, d = read()+1;
    75         f[++cnt] = point(a-1, b-1, i, 1);
    76         f[++cnt] = point(c, d, i, 1);
    77         f[++cnt] = point(a-1, d, i, -1);
    78         f[++cnt] = point(c, b-1, i, -1);
    79         maxy = std::max(maxy, std::max(b, d));
    80     }
    81     cdq(1, cnt);
    82     for (int i=1; i<=m; i++)
    83         printf("%d
    ",ans[i]);
    84     return 0;
    85 }
    另有关cdq的问题详见「初涉cdq」专题
     
     
     
     
    END
     
  • 相关阅读:
    【原创】虚拟机上实现绑定固定IP扩主机容器互访
    docker entrypoint入口文件详解
    数据库博客推荐
    docker下centos安装ping命令
    Dockerfile指令详解
    Elasticsearch Java API 的使用
    docker容器里面安装ssh
    RPM安装命令总结
    Docker容器的跨主机连接
    使用Java程序片段动态生成表格
  • 原文地址:https://www.cnblogs.com/antiquality/p/9028010.html
Copyright © 2011-2022 走看看