~~~题面~~~

题解:

  可以发现这是一道单调栈的题目,首先来考虑数字没有重复时如何统计贡献。

  因为这是一个环,而如果我们从最高的点把环断开,并把最高点放在链的最后面(顺时针移动),那么因为在最高点两侧的点无法互相看见,相当于就把环转化为链的问题了。

  

  因此维护递减的单调栈,如果进来的点比栈顶高就弹出并统计1的贡献。

  但是这样会有遗漏,我们观察什么情况下会遗漏。

  因为是从1开始遍历,因此在前面的节点在遍历到n时完全有可能已经被弹走了,然而因为这是一个环,断开点(最高点)说不定还可以回头看见它。因此这种情况会被遗漏。

  但如果又反着统计又会统计重复,因此考虑不统计最高点的贡献,然后最后再暴力跑2遍统计断开点的贡献。

  但是数字可能有重复,怎么办?

  重复数字会带来很多细节上的问题,比如8333中有5的贡献,而直接弹走显然统计不到5.又比如最大值可能有很多个,因此会将整个数列分为很多小段,,,等等诸如此类。

  因此对于第一种情况,我们记录一下当前栈中每个数字有多少个,因为数字可能很大,但个数不多,因此一开始要离散化一下。

  对于第二种情况,可以在最后暴力统计一下最高点两两搭配的方案数。
  细节很多,注意调试&对拍

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 1001000
#define LL long long int n, id, k, maxn, num, last, cnt;
LL ans;
int ss[AC], t[AC], tot[AC];
int s[AC], top;
bool vis[AC]; inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} inline int get(int x)
{
if(x < ) x += n;
return x > n ? x - n : x;
} int half(int x)
{
int l = , r = cnt;
while(l < r)
{
int mid = (l + r) >> ;
if(ss[mid] == x) return mid;
else if(ss[mid] < x) l = mid + ;
else r = mid - ;
}
return l;
} void pre()
{
n = read();
for(R i = ; i <= n; i ++)
{
ss[i] = read();
if(ss[i] > k) id = i, k = ss[i], num = ;
else if(ss[i] == k) ++ num;
}
id = get(id + );
for(R i = ; i <= n; i ++) t[i] = ss[get(id + i - )];
sort(ss + , ss + n + );
for(R i = ; i <= n; i ++)
if(ss[i] != ss[i + ]) ss[++cnt] = ss[i];
for(R i = ; i <= n; i ++) t[i] = half(t[i]);
k = cnt;
} /*8
3 1 5 7 1 1 7 8 */
void work()
{
for(R i = ; i < n; i ++)//不统计中断处的
{
int tmp = (top && s[] != t[i]);
// printf("%d\n", top);
while(top && s[top] < t[i]) -- tot[s[top]], -- top, ++ ans;
if(top && s[top] != t[i]) ++ ans;
++ tot[t[i]], s[++top] = t[i];
if(tot[t[i]] - ) ans += tot[t[i]] - + tmp;
// printf("%d\n", top);
}
for(R i = ; i <= n; i ++)
{
if(t[i] == k) break;
if(vis[i]) continue;
if(t[i] >= maxn && !vis[i]) ++ ans, vis[i] = true;
upmax(maxn, t[i]);
}
maxn = ;
for(R i = n - ; i; i --)
{
if(t[i] == k) break;
if(t[i] >= maxn && !vis[i]) ++ ans, vis[i] = true;
upmax(maxn, t[i]);
}
if(num > ) ans += num * (num - ) / - (num - ) * (num - ) / ;
printf("%lld\n", ans);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}

[51nod1482]部落信号 单调栈的更多相关文章

  1. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  2. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  3. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

  4. poj 2559 Largest Rectangle in a Histogram - 单调栈

    Largest Rectangle in a Histogram Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 19782 ...

  5. bzoj1510: [POI2006]Kra-The Disks(单调栈)

    这道题可以O(n)解决,用二分还更慢一点 维护一个单调栈,模拟掉盘子的过程就行了 #include<stdio.h> #include<string.h> #include&l ...

  6. BZOJ1057[ZJOI2007]棋盘制作 [单调栈]

    题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...

  7. 洛谷U4859matrix[单调栈]

    题目描述 给一个元素均为正整数的矩阵,上升矩阵的定义为矩阵中每行.每列都是严格递增的. 求给定矩阵中上升子矩阵的数量. 输入输出格式 输入格式: 第一行两个正整数n.m,表示矩阵的行数.列数. 接下来 ...

  8. POJ3250[USACO2006Nov]Bad Hair Day[单调栈]

    Bad Hair Day Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17774   Accepted: 6000 Des ...

  9. CodeForces 548D 单调栈

    Mike and Feet Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Subm ...

随机推荐

  1. PHP-入门指引1

    PHP("PHP: Hypertext Preprocessor",超文本预处理器的字母缩写)是一种被广泛应用的开放源代码的多用途脚本语言,它可嵌入到 HTML中,尤其适合 web ...

  2. 终于搞定了cxgrid的多行表头(转终于搞定了cxgrid的多行表头 )

    终于搞定了cxgrid的多行表头 转自:http://mycreature.blog.163.com/blog/static/556317200772524226400/     这一周都在处理dbg ...

  3. ubuntu配置机器学习环境(三) opencv 安装

    这里使用脚本安装 一些教程里使用cmake 安装,很容易出错的 使用github上的安装脚本,自动化安装 参考链接 Ubuntu $ cd Ubuntu/2.4 $ chmod +x * # 如果要安 ...

  4. 登録更新(BAPI)

    購買管理(MM) * [BAPI_REQUISITION_CREATE] 購買依頼登録 * [BAPI_REQUISITION_CHANGE] 購買依頼変更 * [BAPI_REQUISITION_D ...

  5. WPF中ContextMenu(右键菜单)使用Command在部分控件上默认为灰色的处理方法

    原文:WPF中ContextMenu(右键菜单)使用Command在部分控件上默认为灰色的处理方法 问题描述 今天发现如果我想在一个TextBlock弄一个右键菜单,并且使用Command绑定,结果发 ...

  6. Java:static的作用分析

    static表示“静态”或者“全局”的意思,但在Java中不能在所有类之外定义全局变量,只能通过在一个类中定义公用.静态的变量来实现一个全局变量. 一.静态变量 1. Java中存在两种变量,一种是s ...

  7. 【JS笔记】闭包

    首先看执行环境和作用域的概念.执行环境定义了变量或函数有权访问的其他数据,决定它们的行为,每个执行环境都有一个与其关联的变量对象,保存执行环境中定义的变量.当代码在一个环境中执行时,会创建变量对象的一 ...

  8. Selenium LoadableComponent加载组件

    继承LoadableComponent类可以在打开地址时, 判断浏览器是否打开了预期的网址, 需要重写load()与isLoad()方法: 即使没有定义get()方法, 也可以进行get()方法的调用 ...

  9. 【java并发编程实战】第八章:线程池的使用

    1.线程饥饿锁 定义:在线程池中,如果任务的执行依赖其他任务,那么可能会产生线程饥饿锁.尤其是单线程线程池. 示例: public class ThreadDeadStarveTest { publi ...

  10. Leetcode 672.灯泡开关II

    灯泡开关II 现有一个房间,墙上挂有 n 只已经打开的灯泡和 4 个按钮.在进行了 m 次未知操作后,你需要返回这 n 只灯泡可能有多少种不同的状态. 假设这 n 只灯泡被编号为 [1, 2, 3 . ...