[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 ...
随机推荐
- 关于okHttp框架的使用
在之前的项目中,使用传统的HttpClient来返回一个图片信息流的时候总是报错,最后发现是因为传统的传输方式会对流的大小有限制,当超过某个值的时候就会报异常,最后决定使用OkHttp框架来解决这个问 ...
- thinkphp验证码实现。
作为我大天朝的程序员,如果不会点thinkphp框架确实有点说不过去了(虽然作为菜鸟的我才入坑没几个月).不过不会也没关系,很简单的一个php框架.今天为大家介绍的是thinkphp如何实现验证码的功 ...
- Node.js(一)----安装
1.下载 地址 https://nodejs.org/en/download/ 注: 系统为ubuntu 下载的源码包 tar.gz 或者 wget https://nodejs.org/dist/v ...
- QP之QF原理
1.QP简介: 量子平台(Quantum Platform, 简称QP)是一个用于实时嵌入式系统的软件框架,QP是轻量级的.开源的.基于层次式状态机的.事件驱动的平台. QP包括事件处理器(QEP). ...
- latex03-LaTeX中的中文处理办法
编译含中文的tex文件的前提有三个: 默认编译器为XeLaTeX: 编辑器的默认字体编码格式为UTF-8: 引入ctex的宏包. 效果: 源码: %导言区 \documentclass{article ...
- python2.7练习小例子(二十七)
27):题目:一个5位数,判断它是不是回文数.即12321是回文数,个位与万位相同,十位与千位相同. #!/usr/bin/python # -*- coding: UTF-8 -* ...
- 【转载】[Elasticsearch]ES入门
传送门:http://www.cnblogs.com/xing901022 ES即简单又复杂,你可以快速的实现全文检索,又需要了解复杂的REST API.本篇就通过一些简单的搜索命令,帮助你理解ES的 ...
- CC3200模块的内存地址划分和bootloader(一)
1. CC3200的内存地址划分非常特殊,如果没测试的话,很容易懵逼.我们先看芯片手册里面的内存地址.芯片的RAM是256KB,下图的0x2000 0000-0x2003 FFFF,正好是256KB. ...
- 【APUE】Chapter4 File and Directories
4.1 Introduction unix的文件.目录都被当成文件来看待(vi也可以编辑目录):我猜这样把一起内容都当成文件的原因是便于统一管理权限这类的内容 4.2 stat, fstat, fst ...
- ABP官方文档
https://aspnetboilerplate.com/Pages/Documents/Introduction