~~~题面~~~

题解:

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

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

  

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

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

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

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

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

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

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

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

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define R register int
  4. #define AC 1001000
  5. #define LL long long
  6.  
  7. int n, id, k, maxn, num, last, cnt;
  8. LL ans;
  9. int ss[AC], t[AC], tot[AC];
  10. int s[AC], top;
  11. bool vis[AC];
  12.  
  13. inline int read()
  14. {
  15. int x = ;char c = getchar();
  16. while(c > '' || c < '') c = getchar();
  17. while(c >= '' && c <= '') x = x * + c - '', c = getchar();
  18. return x;
  19. }
  20.  
  21. inline void upmax(int &a, int b)
  22. {
  23. if(b > a) a = b;
  24. }
  25.  
  26. inline int get(int x)
  27. {
  28. if(x < ) x += n;
  29. return x > n ? x - n : x;
  30. }
  31.  
  32. int half(int x)
  33. {
  34. int l = , r = cnt;
  35. while(l < r)
  36. {
  37. int mid = (l + r) >> ;
  38. if(ss[mid] == x) return mid;
  39. else if(ss[mid] < x) l = mid + ;
  40. else r = mid - ;
  41. }
  42. return l;
  43. }
  44.  
  45. void pre()
  46. {
  47. n = read();
  48. for(R i = ; i <= n; i ++)
  49. {
  50. ss[i] = read();
  51. if(ss[i] > k) id = i, k = ss[i], num = ;
  52. else if(ss[i] == k) ++ num;
  53. }
  54. id = get(id + );
  55. for(R i = ; i <= n; i ++) t[i] = ss[get(id + i - )];
  56. sort(ss + , ss + n + );
  57. for(R i = ; i <= n; i ++)
  58. if(ss[i] != ss[i + ]) ss[++cnt] = ss[i];
  59. for(R i = ; i <= n; i ++) t[i] = half(t[i]);
  60. k = cnt;
  61. }
  62.  
  63. /*8
  64. 3 1 5 7 1 1 7 8 */
  65. void work()
  66. {
  67. for(R i = ; i < n; i ++)//不统计中断处的
  68. {
  69. int tmp = (top && s[] != t[i]);
  70. // printf("%d\n", top);
  71. while(top && s[top] < t[i]) -- tot[s[top]], -- top, ++ ans;
  72. if(top && s[top] != t[i]) ++ ans;
  73. ++ tot[t[i]], s[++top] = t[i];
  74. if(tot[t[i]] - ) ans += tot[t[i]] - + tmp;
  75. // printf("%d\n", top);
  76. }
  77. for(R i = ; i <= n; i ++)
  78. {
  79. if(t[i] == k) break;
  80. if(vis[i]) continue;
  81. if(t[i] >= maxn && !vis[i]) ++ ans, vis[i] = true;
  82. upmax(maxn, t[i]);
  83. }
  84. maxn = ;
  85. for(R i = n - ; i; i --)
  86. {
  87. if(t[i] == k) break;
  88. if(t[i] >= maxn && !vis[i]) ++ ans, vis[i] = true;
  89. upmax(maxn, t[i]);
  90. }
  91. if(num > ) ans += num * (num - ) / - (num - ) * (num - ) / ;
  92. printf("%lld\n", ans);
  93. }
  94.  
  95. int main()
  96. {
  97. // freopen("in.in", "r", stdin);
  98. pre();
  99. work();
  100. // fclose(stdin);
  101. return ;
  102. }

[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. zookeeper环境搭建(Linux)

    安装zookeeper 安装jdk(此处省略) 解压tar包并配置变量环境 配置文件修改 将/usr/local/src/zookeeper-3.4.5/conf这个路径下的zoo_sample.cf ...

  2. (数据科学学习手札18)二次判别分析的原理简介&Python与R实现

    上一篇我们介绍了Fisher线性判别分析的原理及实现,而在判别分析中还有一个很重要的分支叫做二次判别,本文就对二次判别进行介绍: 二次判别属于距离判别法中的内容,以两总体距离判别法为例,对总体G1,, ...

  3. Spring配置文件一直报错的根源所在

    跳坑后的感悟总结 Spring在配置文件中经常会报XML错误,以下是几种常见的解决办法 方式一:打开eclipse-->Project-->Clean ;清除一下 方式二:查看xml配置文 ...

  4. Mysql双主操作

    MySQL双主(主主)架构方案   在企业中,数据库高可用一直是企业的重中之重,中小企业很多都是使用mysql主从方案,一主多从,读写分离等,但是单主存在单点故障,从库切换成主库需要作改动.因此,如果 ...

  5. spring 读取properties文件--通过注解方式

    问题: 需要通过properties读取页面的所需楼盘的名称.为了以后便于修改. 解决: 可以通过spring的 PropertiesFactoryBean 读取properties属性,就不需要自己 ...

  6. Qt irrlicht(鬼火)3D引擎 摄像机旋转问题

    点击打开链接Irrlicht中的摄像有一个函数 setUpVector() if (m_device != 0 ) { core::vector3df rotation(y,x,0.f); m_cam ...

  7. session、token、cookie的区别

    token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用co ...

  8. 8.0 TochAction各种用法

    1.滑动---TouchAction  支持相对坐标.绝对坐标.Element 注意看顶部的导入TouchAction这个库.. #实例化 action = TouchAction(driver) # ...

  9. zabbix 一些问题随记

    1. zabbix运行不了,显示被锁,去检查日志中的报错 2. 配置界面,连接不到数据库,检查server配置文件,mysql授权命令要准确,重启 3. 显示没有php文件,下载即可,或者修改网页访问 ...

  10. python 基础篇 15 内置函数和匿名函数

    ------------------------>>>>>>>>>>>>>>>内置函数<<< ...