栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Nowcoder B. 找山坡

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Nowcoder B. 找山坡

Powered by:NEFU AB-IN

Link

文章目录
  • Nowcoder B. 找山坡
    • 题意
    • 思路
    • 代码

Nowcoder B. 找山坡
  • 题意

    母牛哥在电脑面前坐久了,想站起来看看窗外的小山坡,于是就想出了这个问题:
    给定一个大小为n的数组a,序号从1开始,
    计算:
    max{ R - L | 1 <= L <= R <= n, a[L] == a[R], 对于所有i (L <= i <= R), 满足a[i] >= a[L] }.
    也就是找到两个坐标,这两个坐标的值相等,并且他们之间的值都大于等于这两个坐标上的值.
    这两个坐标相减最大能是多少.

  • 思路

    题目解析:找到值相同的两个数,满足两数之间的数都大于等于这两个数,求两数最远隔多远

    • 思路1 树状数组
      这是我最一开始的思路,非常麻烦,可以概括为 树状数组+离散化+双指针
      • 首先,我们可以观察到,如果这两个数前面大于等于他们的数之差 恰好等于 他们之间的下标距离,说明这是符合的一对(因为这就说明了这两个数中间的所有数都大于等于他们),这一点可以仿照树状数组求逆序对来求
      • 其次,上面的等式可以稍做优化,记下每个值的 k = (前面大于等于他们的数 - 下标),为每个值开辟一个vector,把是这个值的 k 和 下标 记下来
      • 之后,对于每个值的vector进行升序排序,遇到相等的k,就更新结果,和此下标之差取最大值即可,这个操作用双指针即可完成
      • 注意!
        • a[i]的范围,存在0,所以要+1;最大1e9,所以要离散化
    • 思路2 单调栈
      其实一眼就是单调栈的板子题,每次把大于等于它的数加入进去,如果带进入的数比栈顶小,那么就弹出栈,直到大于等于时,如果此时栈顶和带进入的数相等了,说明找到一对,更新最大值即可
      (策略是正确的,因为每次处理离的最近的,保证每对符合要求都能处理到)
    • 思路3 线段树
      线段树板子题,维护区间最小值即可,采用链表跳转到相等的值,判断两者中间的区间最小值和其值的关系,代码就不实现了
  • 代码
    • 思路1 树状数组

      #include 
      using namespace std;
      
      #define int long long
      #define lowbit(x) x & -x
      #define SZ(X) ((int)X.size())
      const int N = 1e6 + 10;
      int tr[N];
      const int INF = 0x3f3f3f3f;
      typedef pair PII;
      
      void add(int x)
      {
          for (int i = x; i < N; i += lowbit(i))
          {
              tr[i] += 1;
          }
      }
      int query(int x)
      {
          int res = 0;
          for (int i = x; i; i -= lowbit(i))
          {
              res += tr[i];
          }
          return res;
      }
      vector  g[N];
      vector alls = {-INF}; // 存储所有待离散化的值
      signed main()
      {
          int n;
          scanf("%lld", &n);
          vector a(n + 1);
          for (int i = 1; i <= n; ++i)
          {
              scanf("%lld", &a[i]);
              a[i]++;
              alls.push_back(a[i]);
          }
          // 离散化
          sort(alls.begin(), alls.end()); // 将所有值排序
          alls.erase(unique(alls.begin(), alls.end()), alls.end());   // 去掉重复元素
          
          for (int i = 1; i <= n; ++i)
          {
              int id = lower_bound(alls.begin(), alls.end(), a[i]) - alls.begin();
              add(id);
              int num = (i - query(id - 1)); // 查询比它大于等于的数
              g[id].push_back({num - i, i});
          }
          
          int ans = 0;
          for (auto lst : g) // 遍历每个数值的vector
          {
              sort(lst.begin(), lst.end());
              int l = 0, r = 0;
              while (l <= r && l < SZ(lst))
              {
                  while (r < SZ(lst) && lst[l].first == lst[r].first)
                      r++;
                  ans = max(ans, lst[r - 1].second - lst[l].second);
                  l = r;
              }
          }
          printf("%lldn", ans);
          return 0;
      }
      

    • 思路2 单调栈

      #include 
      
      using namespace std;
      #define int long long
      #define SZ(X) ((int)X.size())
      typedef pair PII;
      
      signed main()
      {
          int n;
          scanf("%lld", &n);
          vector a(n + 1);
          for (int i = 1; i <= n; ++i)
              scanf("%lld", &a[i]);
      
          int ans = 0;
          stack s; // first 值 second 下标
          for (int i = 1; i <= n; ++i)
          {
              while (SZ(s) && s.top().first > a[i])
                  s.pop();
              if (SZ(s) && s.top().first == a[i])
                  ans = max(ans, i - s.top().second);
              else s.push({a[i], i});
          }
          cout << ans;
          return 0;
      }
      
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/869587.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号