• 离散化+线段树+二分查找


    牛客 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
     
     
     
  • 相关阅读:
    jesperreport+ireport简单理解
    tomcat服务器奇异事件
    Spring+SpringMvc+Mybatis整合注意事项
    Websocket简单例子
    uploadify前台上传文件,java后台处理的例子
    违反完整约束条件 (XXX)
    插入排序
    选择排序
    冒泡算法(思路二)
    2-3树
  • 原文地址:https://www.cnblogs.com/daybreaking/p/11749067.html
Copyright © 2020-2023  润新知