[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 ...
随机推荐
- Python的virtualenv你用过吗?
1. 为什么要有virtualenv 在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾 ...
- Laravel 5.5搭建(lunix-ubuntu)
基本配置 PHP >= 7.0.0 PHP OpenSSL 扩展 PHP PDO 扩展 PHP Tokenizer 扩展 PHP XML 扩展 1:nginx sudo apt-get upda ...
- python学习之字符串常用方法和格式化字符串
Python中的字符串同样适用标准的序列操作(索引,分片,乘法,成员判断,求长度,取最小值和最大值),但因为字符串是不可变的,因此字符串不支持分片赋值. s='http://www.baidu.com ...
- 宝塔漏洞 XSS窃取宝塔面板管理员漏洞 高危
宝塔是近几年刚崛起的一款服务器面板,深受各大站长的喜欢,windows2003 windows2008windosws 2012系统,linux centos deepin debian fedora ...
- Java学习笔记六:Java的流程控制语句之if语句
Java的流程控制语句之if语句 一:Java条件语句之if: 我们经常需要先做判断,然后才决定是否要做某件事情.例如,如果考试成绩大于 90 分,则奖励一朵小红花 .对于这种“需要先判断条件,条件满 ...
- Leecode刷题之旅-C语言/python-118杨辉三角
/* * @lc app=leetcode.cn id=118 lang=c * * [118] 杨辉三角 * * https://leetcode-cn.com/problems/pascals-t ...
- Eclipse_安装SAP_HANA数据库插件
1.对于Eclipse Oxygen,请添加URL https://tools.hana.ondemand.com/oxygen 2.对于Eclipse luna,请添加URL https:/ ...
- PHP.39-扩展-锁机制解决并发-MySQL锁、PHP文件锁
锁机制适用于高并发场景:高并发订单.秒杀…… apache压力测试 Mysql锁详解 语法 加锁:LOCK TABLE 表名1 READ|WRITE, 表名2 READ|WRITE ......... ...
- vs编译报错 BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
1.重复释放内存导致,new delete和malloc free两个组合分配的堆空间都不能重复释放两次: 2.用delete或者free释放栈空间导致内存空间被破坏(栈空间内存的头部有系统写入的一些 ...
- C#3DES加密了解一下
最近一个项目中,因为服务端是用的java开发的,客户端是用的C#,由于通信部分采用到了3DES加密,所以做个记录,以备以后需要的时候直接用. 这是对方(java)的加密算法,和网上流传的代码也差不多( ...