[51nod1482]部落信号 单调栈
题解:
可以发现这是一道单调栈的题目,首先来考虑数字没有重复时如何统计贡献。
因为这是一个环,而如果我们从最高的点把环断开,并把最高点放在链的最后面(顺时针移动),那么因为在最高点两侧的点无法互相看见,相当于就把环转化为链的问题了。

因此维护递减的单调栈,如果进来的点比栈顶高就弹出并统计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]部落信号 单调栈的更多相关文章
- BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]
1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec Memory Limit: 162 MBSubmit: 8748 Solved: 3835[Submi ...
- BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]
4453: cys就是要拿英魂! Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 90 Solved: 46[Submit][Status][Discu ...
- BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]
3238: [Ahoi2013]差异 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2326 Solved: 1054[Submit][Status ...
- poj 2559 Largest Rectangle in a Histogram - 单调栈
Largest Rectangle in a Histogram Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 19782 ...
- bzoj1510: [POI2006]Kra-The Disks(单调栈)
这道题可以O(n)解决,用二分还更慢一点 维护一个单调栈,模拟掉盘子的过程就行了 #include<stdio.h> #include<string.h> #include&l ...
- BZOJ1057[ZJOI2007]棋盘制作 [单调栈]
题目描述 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑白相间的方阵,对应八八六十四卦,黑白对应阴阳. 而我们的 ...
- 洛谷U4859matrix[单调栈]
题目描述 给一个元素均为正整数的矩阵,上升矩阵的定义为矩阵中每行.每列都是严格递增的. 求给定矩阵中上升子矩阵的数量. 输入输出格式 输入格式: 第一行两个正整数n.m,表示矩阵的行数.列数. 接下来 ...
- POJ3250[USACO2006Nov]Bad Hair Day[单调栈]
Bad Hair Day Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 17774 Accepted: 6000 Des ...
- CodeForces 548D 单调栈
Mike and Feet Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Subm ...
随机推荐
- React学习(4)——向服务器请求数据并显示
本文中涉及到的技术包括:node.js/express服务器的搭建.fetch发送数据请求. 在之前的几篇文章中,介绍了如何搭建基础的React项目,以及一些简单知识,现在,我们还需要掌握如何用Rea ...
- 处理laravel表单提交默认将空值转为null的问题
比如表单提交,如果我们提交了这个字段,但是这个字段为空字符串.在Laravel中会自动转义成Null. 处理这个问题,直到找到中间件\vendor\laravel\framework\src\Illu ...
- Python的scrapy之爬取boss直聘网站
在我们的项目中,单单分析一个51job网站的工作职位可能爬取结果不太理想,所以我又爬取了boss直聘网的工作,不过boss直聘的网站一次只能展示300个职位,所以我们一次也只能爬取300个职位. jo ...
- ruby 第三方模块unirest使用
Creating Requests require 'unirest' response = Unirest.post 'http://httpbin.org/post', headers:{ Acc ...
- 抽象类实验:SIM卡抽象
抽象SIM: package sim_package; public abstract class SIM { public abstract String giveNumber(); public ...
- 002---tcp/ip五层详解
tcp/ip 五层模型讲解 越靠底层就越接近硬件,越靠上层越接近用户.先从底层看起,理解整个互联网通信的原理. 物理层(传输电信号) 孤立的计算机想要一起玩.就必须用硬件在计算机之间完成组网.以硬件做 ...
- R语言绘图:直方图
使用ggplot2包绘制直方图 ######*****绘制直方图代码*****####### data1 <- data0[(data0[, 2] <= 500) & (data0 ...
- 什么是Session共享?请举出使用场景
是指在一个浏览器对应多个Web服务时,服务端的Session数据需要共享.例如单点登录.Web服务器集群等场景都需要用到.多子服务. Session共享有多种解决方案,例如Tomcat插件,我最喜欢的 ...
- JDBC 的使用
使用 MariaDB,JDBC 所有操作全部使用预处理 SQL 的基本类型与 Java 类型的对应关系 CHAR(N) - String VARCHAR(N) - String BOOLEN - bo ...
- PHP.44-TP框架商城应用实例-后台19-权限管理-RBAC需求分析
RBAC:Role Based Access Control:基于角色的访问控制 需求分析:[类似效果如下图] 1.权限,角色,管理员 2.权限管理[无限级] 注意:权限会被分配给角色,而不是给管理员 ...