2017京东笔试编程题-保卫方案 | Codeforces Beta Round #5 E.Bindian Signalizing

cf上的原题,地址在:http://codeforces.com/contest/5/problem/E
题意

大意是给你围成了一个环的序列,要求所有的点对(i,j)的数目,满足i < j,且i~j之间没有大于i和j的数,之间是指i+1~j-1或i-1~1~n~j+1。

思路

如果这个序列不是环形的,那么仅仅维护一个非增队列就可以统计答案了,然而对于对于环形序列,队首和队首之前的点还可以通过“另一条路”和当前点配对,对于这一部分答案,如果我们维护下队首和队首之前的数的非降序列,那么答案在非降序列上形成了一个区间,由于后缀最大值单调不增,所以可以这个区间会整体向下移动,这样一来复杂度就是线性的了。
比较巧妙的方法是,将整个序列循环移动下,使得最大值在最前面,那么显然这个最大值在非增队列中就会一直占据队首了,对于第二部分的答案,上面提到的那个“队首和队首之前的数的非降序列”就变成了队首这一个数了,因此只需分类讨论队首是否能通过“另一条路”和当前点配对即可,简单很多。
另外,对于单调队列中相等的数,缩成一个数,同时加一个域表示个数,后续处理起来非常方便。

source
#include <bits/stdc++.h>
#ifdef LOCAL
#include "local.h"
#endif // LOCAL
using namespace std;
const int N = 1e6 + 7;
struct Node {
  int val, c;
  Node() {}
  Node(int val, int c) {
    this->val = val;
    this->c = c;
  }
};
int a[N], n, tq, suf[N];
Node que[N];
int main() {
  cin >> n;
  for (int i = 0; i < n; i++) scanf("%d", a + i);
  rotate(a, max_element(a, a + n), a + n);
  suf[n] = 0;
  for (int i = n - 1; i >= 0; i--) suf[i] = max(suf[i + 1], a[i]);
  long long ans = 0;
  for (int i = 0; i < n; i++) {
    while (tq && a[i] > que[tq - 1].val) {
      ans += que[tq - 1].c;
      tq--;
    }
    if (tq && a[i] == que[tq - 1].val) que[tq - 1].c++;
    else que[tq++] = Node(a[i], 1);
    if (que[tq - 1].c == 1) {
      if (tq > 1) {
        ans++;
        if (tq > 2 && suf[i + 1] <= a[i]) ans ++;
        if (tq == 2 && suf[i + 1] <= a[i]) ans += que[0].c > 1;
      }
    }
    else {
      ans += que[tq - 1].c - 1;
      if (tq == 2) {
        ans++;
        if (que[0].c > 1 && suf[i + 1] <= a[i]) ans ++;
      }
      if (tq > 2) {
        ans++;
        if (suf[i + 1] <= a[i]) ans ++;
      }
    }
  }
  cout << ans << endl;
  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值