zoukankan      html  css  js  c++  java
  • 楼房重建 线段树

    ~~~题面~~~

    题解:

    一栋楼是否已经被前面的楼房遮挡住,可以利用斜率来判断。

    因此将原序列转化为斜率。

    然后直接用线段树维护一下每个区间最多能看见多少楼房即可。

    在更新区间的时候需要在线段树上二分,因为左区间是肯定可以取的,然后设左区间的最大值为k,

    那么右区间的贡献就是大于k的最长上升子序列,二分即可。

    建议画画图,还是很好理解的。

    注意:这里其实并不是维护的传统意义上的最长递增子序列,因为这里的子序列强制从第一个开始了,所以代码中的注释其实有点问题,,(算法是对的)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 100100
     5 #define ac 600000
     6 int n, m;
     7 int tree[ac], l[ac], r[ac];//维护最长上升子序列和
     8 double mx[ac];
     9 
    10 inline int read()
    11 {
    12     int x = 0;char c = getchar();
    13     while(c > '9' || c < '0') c = getchar();
    14     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    15     return x;
    16 }
    17 
    18 int cal(int x, double k)//当前点,大于k的最长上升子序列
    19 {//计算在一段区间内大于k的可以被看见的有多少个
    20     if(l[x] == r[x]) return mx[x] > k;
    21     if(mx[x] <= k) return 0;
    22     if(mx[x * 2] < k) return cal(x * 2 + 1, k);
    23     else return tree[x] - tree[x * 2] + cal(x * 2, k);
    24 }
    25 
    26 void update(int x)
    27 {
    28     mx[x] = max(mx[x * 2], mx[x * 2 + 1]);
    29     tree[x] = tree[x * 2] + cal(x * 2 + 1, mx[x * 2]);
    30 }
    31 
    32 void build(int x, int ll, int rr)
    33 {
    34     l[x] = ll, r[x] = rr;
    35     if(ll == rr) return ;
    36     int mid = (ll + rr) >> 1;
    37     build(x * 2, ll, mid);
    38     build(x * 2 + 1, mid + 1, rr);
    39 }
    40 
    41 void change(int x, int w, double t)//当前点,目标点, 改成什么
    42 {//单点修改并维护新值
    43     if(l[x] == r[x])
    44     {
    45         mx[x] = t;
    46         tree[x] = 1;
    47         return ;
    48     }
    49     int mid = (l[x] + r[x]) >> 1;
    50     if(w <= mid) change(x * 2, w, t);
    51     else change(x * 2 + 1, w, t); 
    52     update(x);
    53 }
    54 
    55 void pre()
    56 {
    57     n = read(), m = read();
    58     build(1, 1, n);
    59 }
    60 
    61 void work()
    62 {
    63     int a, b;
    64     for(R i = 1; i <= m; i ++)
    65     {
    66         a = read(), b = read();
    67         change(1, a, (double)b / (double)a);//这个也要用double
    68         printf("%d
    ", tree[1]);
    69     }
    70 }
    71 
    72 int main()
    73 {
    74 //    freopen("in.in", "r", stdin);
    75     pre();
    76     work();
    77 //    fclose(stdin);
    78     return 0;
    79 }
    View Code
  • 相关阅读:
    2018-2019-2 网络对抗技术 20165322 Exp8 Web基础
    2018-2019-2 网络对抗技术 20165322 Exp7 网络欺诈防范
    2018-2019-2 网络对抗技术 20165322 Exp6 信息搜集与漏洞扫描
    2018-2019-2 网络对抗技术 20165322 Exp5 MSF基础应用
    2018-2019-2 网络对抗技术 20165322 Exp4 恶意代码分析
    2018-2019-2 网络对抗技术 20165322 Exp3 免杀原理与实践
    2018-2019-2 网络对抗技术 20165322 Exp2 后门原理与实践
    20175104 李屹哲 exp9 web安全基础实践
    20175104 李屹哲 exp8 Web基础
    20175104 李屹哲 EXP7 网络欺诈技术防范
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9583943.html
Copyright © 2011-2022 走看看