zoukankan      html  css  js  c++  java
  • 离散化+线段树+二分查找

    牛客 Forsaken的三维数点

    题目描述 

            Forsaken现在在一个三维空间中,空间中每个点都可以用(x,y,z)(x,y,z)表示。突然,三维空间的主人出现了,如果Forsaken想要继续在三维空间中呆下去,他就必须回答三维空间主人的问题。
            主人会在空间中坐标为(x,y,z)(x,y,z)处加一点能量值,当他加了一定的次数之后,他会问Forsaken一个问题:如果坐标(0,0,0)(0,0,0)为球心,那么至少需要多大的半径才能使得球内的能量值总和大于或者等于kk,在这里,半径为00也是可以的。这对于Forsaken来说实在是太难了,因此他把这个问题交给了你。

    输入描述:

    第一行一个nn表示操作的次数。
    接下来每行首先一个整数opop表示操作的种类。
    如果op = 1op=1,接下来33个整数x,y,zx,y,z表示能量值增加的坐标。
    如果op =2op=2,接下来一个整数kk表示要求的能量值总和。

    输出描述:

    对于每个op=2op=2的操作,输出一个整数表示球的半径。(数据保证至少有一个22操作)
    如果没有满足答案的半径,输出-11。
    示例1

    输入

    复制
    2
    1 1 1 1
    2 1

    输出

    复制
    2

    备注:

    1 n2e5
    1 op2
    -1e5 x,y,z1e5
    0k2e5
     
    首先降维,因为题目问题的关键是举例,所以通过sqrt(x^2 + y ^2 + z ^2)降为一维。
     
    解法一:离散化+线段树+二分查找
     
    题目坐标最大是1e5,平方后是1e10,直接建树无法实现。但是观察数据发现,最多有1e5个输入,也就是说每次做多有1e5个点,因此想到离散化。
    离散化的前提是知道全部的输入,所以想到把问题离线处理。
    这样,把所有的距离输入后,从小到大排一遍序,便离散处理完了。
     
    如何建树?
    线段树中每一个中间节点存储的是它左右孩子节点的能量值的和。
    更新操作时,只更新对应的点。
     
    对于题目问题的查询操作:
    每一个节点可以分为两部分,前半部分 和 后半部分。
    假设查询操作的值为k,
    如果k大于结点的值,则直接返回-1.
    如果k小于等于前半部分的能量值,则进入前半部分继续查找k。否则,进入后半部分查询 k - sum[i << 1] 。
     
    AC代码:
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <math.h>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <map>
      8 #include <stack>
      9 #include <deque>
     10 #include <iostream>
     11 using namespace std;
     12 typedef long long LL;
     13 const LL N = 200009;
     14   
     15 struct con
     16 {
     17     LL l, r;
     18 } con[4 * N];
     19 LL sum[4 * N];
     20   
     21 LL tri[200009];
     22 LL distill[200009];
     23 struct q
     24 {
     25     LL k;
     26     LL i;
     27 } q[200009];
     28   
     29 map<LL, LL> qq;
     30   
     31 void pushUp(LL i)
     32 {
     33     sum[i] = sum[i << 1] + sum[i << 1 | 1];
     34 }
     35   
     36 void build(LL i, LL l, LL r)
     37 {
     38     con[i].l = l;
     39     con[i].r = r;
     40     if (con[i].l == con[i].r)
     41     {
     42         sum[i] = 0;
     43         return;
     44     }
     45     LL mid = (con[i].l + con[i].r) >> 1;
     46     build(i << 1, l, mid);
     47     build(i << 1 | 1, mid + 1, r);
     48   
     49     pushUp(i);
     50 }
     51   
     52 void update(LL i, LL l, LL r)
     53 {
     54    // cout << " ** " << i << " " << con[i].l << " " << con[i].r << "  " << l << " " << r << endl;
     55     if (con[i].l == l && con[i].r == r)
     56     {
     57         sum[i]++;
     58         return;
     59     }
     60     LL mid = (con[i].l + con[i].r) >> 1;
     61   
     62     if (l > mid)
     63     {
     64         update(i << 1 | 1, l, r);
     65     }
     66     else if (r <= mid)
     67     {
     68         update(i << 1, l, r);
     69     }
     70     else
     71     {
     72         update(i << 1, l, mid);
     73         update(i << 1 | 1, mid + 1, r);
     74     }
     75   
     76     pushUp(i);
     77 }
     78   
     79 LL query(LL i, LL k)
     80 {
     81     //cout << " ?? " << i << " " << con[i].l << " " << con[i].r << " " << sum[i] << "   " << k << endl;
     82     if (sum[i] < k)
     83     {
     84         return -1;
     85     }
     86   
     87     if (con[i].l == con[i].r)
     88     {
     89         return con[i].l;
     90     }
     91   
     92     if (k <= sum[i << 1])
     93     {
     94         return query(i << 1, k);
     95     }
     96     else
     97     {
     98         return query(i << 1 | 1, k - sum[i << 1]);
     99     }
    100 }
    101   
    102 LL dis(LL x, LL y, LL z)
    103 {
    104     return x * x + y * y + z * z;
    105 }
    106   
    107 int main()
    108 {
    109     LL n, i, j, m, mid, tmp;
    110     LL k, x, y, z, cnt1 = 0, cnt2 = 0, cnt3 = 0;
    111   
    112     scanf("%lld", &n);
    113     for (i = 1; i <= n; i++)
    114     {
    115         scanf("%lld", &m);
    116         if (m == 1)
    117         {
    118             scanf("%lld%lld%lld", &x, &y, &z);
    119             mid = dis(x, y, z);
    120             if (qq[mid] == 0)
    121             {
    122                 distill[++cnt3] = mid;
    123                 qq[mid] = 1;
    124             }
    125   
    126             tri[++cnt1] = mid;
    127         }
    128         else
    129         {
    130             scanf("%lld", &q[++cnt2].k);
    131             q[cnt2].i = i;
    132             tri[++cnt1] = 0;
    133         }
    134     }
    135     sort(distill + 1, distill + 1 + cnt3);
    136     for (i = 1; i <= cnt3; i++)
    137     {
    138         qq[distill[i]] = i;
    139     }
    140   
    141 //    cout << endl << endl;
    142 //    for(i = 1; i <= cnt1; i++)
    143 //        cout << i << " " << tri[i] << endl;
    144 //
    145 //    cout << endl << endl;
    146 //    for(i = 1; i <= cnt2; i++)
    147 //        cout << q[i].i << " " << q[i].k << endl;
    148 //
    149 //    cout << endl << endl;
    150 //    for(i = 1; i <= cnt3; i++)
    151 //        cout << distill[i] << " " ;
    152 //
    153 //    cout << endl << endl;
    154   
    155     if(cnt3 < 1)
    156     {
    157         for(i = 1; i <= cnt2; i++)
    158         {
    159             if(q[i].k == 0)
    160                 printf("0
    ");
    161             else
    162                 printf("-1
    ");
    163         }
    164     }
    165     else
    166     {
    167         build(1, 1, cnt3);
    168       //  cout << "hello " << endl;
    169   
    170         j = 1;
    171         for (i = 1; i <= cnt2; i++)
    172         {
    173         //    cout << "world!" << endl;
    174             while (j < q[i].i)
    175             {
    176           //      cout << " ** " << qq[tri[j]] << " " << cnt3 << endl;
    177                 update(1, qq[tri[j]], qq[tri[j]]);
    178                 j++;
    179             }
    180   
    181             if(q[i].k == 0)
    182             {
    183                 printf("0
    ");
    184             }
    185             else
    186             {
    187                 tmp = query(1, q[i].k);
    188                 if (tmp == -1)
    189                     printf("-1
    ");
    190                 else
    191                 {
    192                     LL ans = ceil(sqrt((double)distill[tmp]));
    193                     printf("%lld
    ", ans);
    194                 }
    195             }
    196   
    197             j++;
    198         }
    199     }
    200   
    201   
    202     return 0;
    203 }
    View Code
     
    解法二:简单线段树
     
     
    因为查询的是距离,且距离最多是1e5A,并且题目要求的是向上取整的整数值,所以直接按ceil(sqrt(x^2 + y ^2 + z ^2))距离建树就好了。
     
    AC代码:
      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <math.h>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <map>
      8 #include <stack>
      9 #include <deque>
     10 #include <iostream>
     11 using namespace std;
     12 typedef long long LL;
     13 const LL N = 200009;
     14  
     15 struct con
     16 {
     17     LL l, r;
     18 } con[4 * N];
     19 LL sum[4 * N];
     20 LL len;
     21  
     22 void pushUp(LL i)
     23 {
     24     sum[i] = sum[i << 1] + sum[i << 1 | 1];
     25 }
     26  
     27 void build(LL i, LL l, LL r)
     28 {
     29     con[i].l = l;
     30     con[i].r = r;
     31     if (con[i].l == con[i].r)
     32     {
     33         sum[i] = 0;
     34         return;
     35     }
     36     LL mid = (con[i].l + con[i].r) >> 1;
     37     build(i << 1, l, mid);
     38     build(i << 1 | 1, mid + 1, r);
     39  
     40     //pushUp(i);
     41 }
     42  
     43 void update(LL i, LL l, LL r)
     44 {
     45     // cout << " ** " << i << " " << con[i].l << " " << con[i].r << "  " << l << " " << r << endl;
     46  
     47     //if (con[i].l == l && con[i].r == r)
     48     if (con[i].l == l && con[i].r == r)
     49     {
     50         sum[i]++;
     51         return;
     52     }
     53     //LL mid = (con[i].l + con[i].r) >> 1;
     54  
     55     LL m = (con[i].l + con[i].r) >> 1;
     56     if (r <= m)
     57         update(i << 1, l, r);
     58     else
     59     {
     60         if (l > m)
     61             update(i << 1 | 1, l, r);
     62         else
     63         {
     64             update(i << 1, l, m);
     65             update(i << 1 | 1, m + 1, r);
     66         }
     67     }
     68 /*
     69     LL mid = (l + r) >> 1;
     70     if (len <= mid)
     71         update(i << 1, l, mid);
     72     else
     73     {
     74         update(i << 1 | 1, mid + 1, r);
     75     }
     76 */
     77     pushUp(i);
     78 }
     79  
     80 LL query(LL i, LL k)
     81 {
     82     // cout << " ?? " << i << " " << con[i].l << " " << con[i].r << " " << sum[i] << "   " << k << endl;
     83     if (sum[i] < k)
     84     {
     85         return -1;
     86     }
     87  
     88     if (con[i].l == con[i].r)
     89     {
     90         return con[i].r;
     91     }
     92  
     93     if (k <= sum[i << 1])
     94     {
     95         return query(i << 1, k);
     96     }
     97     else
     98     {
     99         return query(i << 1 | 1, k - sum[i << 1]);
    100     }
    101 }
    102  
    103 LL dis(LL x, LL y, LL z)
    104 {
    105     return ceil(sqrt(x * x + y * y + z * z));
    106 }
    107  
    108 int main()
    109 {
    110     LL n, i, j, m, ans;
    111     LL k, x, y, z;
    112  
    113     build(1, 0, N);
    114     scanf("%lld", &n);
    115     for (i = 1; i <= n; i++)
    116     {
    117         scanf("%lld", &m);
    118         if (m == 1)
    119         {
    120             scanf("%lld%lld%lld", &x, &y, &z);
    121             len = dis(x, y, z);
    122             update(1, len, len);
    123         }
    124         else
    125         {
    126             scanf("%lld", &k);
    127             if (k == 0)
    128                 ans = 0;
    129             else
    130             {
    131                 ans = query(1, k);
    132             }
    133             printf("%lld
    ", ans);
    134         }
    135     }
    136  
    137     return 0;
    138 }
    View Code
     
     
     
  • 相关阅读:
    在Centos 7下编译openwrt+njit-client
    开博随笔
    Chapter 6. Statements
    Chapter 4. Arrays and Pointers
    Chapter 3. Library Types
    Chapter 2.  Variables and Basic Types
    关于stm32不常用的中断,如何添加, 比如timer10 timer11等
    keil 报错 expected an identifier
    案例分析 串口的地不要接到电源上 会烧掉
    案例分析 CAN OPEN 调试记录 进度
  • 原文地址:https://www.cnblogs.com/daybreaking/p/11749067.html
Copyright © 2011-2022 走看看