http://codeforces.com/problemset/problem/5/E

众所周知,在很久以前,在今天的 Berland 地区,居住着 Bindian 部落。他们的首都被 n 座山所环绕,形成了一个圆形。在每座山上,有一名看守人,昼夜看守着相邻的山。

万一出现了任何危险,看守人可以在山上点燃烽火。如果连接两座山的圆弧上,没有任何山高于这两座山中的任何一座,那么这两座山的一个看守人可以看见另一个看守人的信号。对于任意两座山,由于存在两条不同的圆弧连接着它们,如果在至少一条圆弧上满足前述条件,信号就能被看见。例如,对于任意两个相邻的看守人,一方的信号将能够被另一方看见。

这个守护系统的一个重要特性,就是能够相互看见对方信号的看守人“成对”的数目。请根据给定各山的高度,求出这样的“成对”数目。

输入
输入数据的第一行,包含了一个整数 n ( ≤ n ≤ ), n — 环绕首都的山的数量。第二行包含了 n 个数字 — 按顺时针顺序的各山的高度。所有的高度数字为整数,介于 到 之间。 输出
打印所要求的“成对”数目。

题意

首先遇到的就是对环的操作,很显然直接在环上操作是不那么容易的,开始想到对整个链进行延长两倍的操作进行处理,但是这样会很麻烦,难以下手

由于这题的特殊特性,当我们尝试把最高的山脉放在链的最左边时,整个环就变成了一个相同题意下的链,可以方便操作很多。

一个小技巧在寻找最大值的时候用一个变量存储最大值下标可以很便捷

然后遇到的问题就是求对数,开始想到了单调队列去做,但是因为会有类似 1 1 2 2这样的样例,单调队列很难维护

只能考虑用其他的方法

我们假设每一个山脉都是对数里面较低的山脉,我们对每个山脉计算的就只有两边比他大的山脉。

由此得到维护一个left数组,right数组表示这个山脉两边比他高的山脉,如果存在就ans++

但是还有一个问题就是1 1 1 1 这个样例,所有等高山脉是可以互相看见的。我们还需要计算l 到 r 之间和这个山脉高度相等的山脉加上去。

加两边会导致重复计算,如果每一个山脉都只加右边,就可以完美规避这个问题,也就是说用一个same数组来存储这个i 到 right[i]之间有多少和他高度相同的山脉

求left right same的方法当然不是暴力,用dp的思想可以在线性的时间内解决这个问题

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 1e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,tmp,K;
int a[maxn];
int b[maxn];
int Left[maxn],Right[maxn],same[maxn];
int main()
{
Sca(N);
For(i,,N) Sca(a[i]);
int MAX = ;
For(i,,N){
if(a[i] > a[MAX]) MAX = i;
}
For(i,,MAX - ){
b[N - MAX + + i] = a[i];
}
For(i,MAX,N){
b[i - MAX + ] = a[i];
}
int cnt = ;
Left[] = ;
For(i,,N){
Left[i] = i - ;
while(Left[i] > && b[Left[i]] <= b[i]){
Left[i] = Left[Left[i]];
}
}
_For(i,N,){
Right[i] = i + ;
while(Right[i] <= N && b[Right[i]] < b[i]){
Right[i] = Right[Right[i]];
}
if(Right[i] <= N && b[Right[i]] == b[i]){
same[i] = same[Right[i]] + ;
Right[i] = Right[Right[i]];
}
}
LL ans = ;
For(i,,N){
ans += same[i] + ;
if(Left[i] == && Right[i] == N + ){
ans--;
}
}
Prl(ans);
#ifdef VSCode
system("pause");
#endif
return ;
}

CodeForces5E 环转链,dp思想的更多相关文章

  1. P1880 [NOI1995]石子合并 区间dp+拆环成链

    思路 :一道经典的区间dp  唯一不同的时候 终点和起点相连  所以要拆环成链  只需要把1-n的数组在n+1-2*n复制一遍就行了 #include<bits/stdc++.h> usi ...

  2. 【BZOJ-2937】建造酿酒厂 前缀和 + 展环为链 + 乱搞

    2937: [Poi2000]建造酿酒厂 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 70  Solved: 24[Submit][Status][D ...

  3. 到底什么是dp思想(内含大量经典例题,附带详细解析)

    期末了,通过写博客的方式复习一下dp,把自己理解的dp思想通过样例全部说出来 说说我所理解的dp思想 dp一般用于解决多阶段决策问题,即每个阶段都要做一个决策,全部的决策是一个决策序列,要你求一个 最 ...

  4. hdu 3030 Increasing Speed Limits (离散化+树状数组+DP思想)

    Increasing Speed Limits Time Limit: 2000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  5. DP思想在斐波那契数列递归求解中的应用

    斐波那契数列:1, 1, 2, 3, 5, 8, 13,...,即 f(n) = f(n-1) + f(n-2). 求第n个数的值. 方法一:迭代 public static int iterativ ...

  6. hdu 4612 Warm up 双连通+树形dp思想

    Warm up Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total S ...

  7. DAG上dp思想

    DAG上DP的思想 在下最近刷了几道DAG图上dp的题目.要提到的第一道是NOIP原题<最优贸易>.这是一个缩点后带点权的DAG上dp,它同时规定了起点和终点.第二道是洛谷上的NOI导刊题 ...

  8. 湖南省第十二届大学生计算机程序设计竞赛 B 有向无环图 拓扑DP

    1804: 有向无环图 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 187  Solved: 80[Submit][Status][Web Board ...

  9. 图论 公约数 找环和链 BZOJ [NOI2008 假面舞会]

    BZOJ 1064: [Noi2008]假面舞会 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1655  Solved: 798[Submit][S ...

随机推荐

  1. Vivado安装、生成bit文件及烧录FPGA的简要流程

    https://wenku.baidu.com/view/0294cbb3bb4cf7ec4bfed01a.html

  2. Draw your Next App Idea with Ink to Code

    Imagine that you’ve just been struck by inspiration for your next great app. You might start by jott ...

  3. 做接口自动化时候,一些登录头信息可以通过aop的方式进行增强

    做接口自动化时候,一些登录头信息可以通过aop的方式进行增强

  4. Base64 总结

    Base64编码是解决一些无法打印的字符无法显示的问题,将8位的ascii编码转换为6位的表示64个可见字符的算法. 具体而言,首先将编码每三个分成一组,将三个字符转换为总长为24位的二进制 数字,将 ...

  5. 利用random模块生成验证码

    random模块 该模块用于数学或者数据相关的领域,使用方法非常简单下面介绍常用的放法 1.随机小数 random.random() 2.随机整数random.randint(1,5) # 大于等于1 ...

  6. Cent OS安装使用ffmpeg(完整版)

    Cent OS安装使用ffmpeg centos作为主流后台linux 系统,ffmpeg作为视频流解析的主力,尤其是ffmpeg配合opencv使用,则是视觉操作的基础 版本: ffmpeg3.1 ...

  7. Codeforces Round #518 (Div. 2) B. LCM gcd+唯一分解定律

    题意:给出b 求lcm(a,b)/a 在b从1-1e18有多少个不同得结果 思路lcm*gcd=a*b  转换成    b/gcd(a,b) 也就是看gcd(a,b)有多少个值  可以把b 由唯一分解 ...

  8. 51Nod1824 染色游戏 【Lucas定理】【FMT】【位运算】

    我的FMT是在VFleaKing的论文中学到的.51Nod的评测机好恶心. 题目分析: 题目很明显是要你求一个类似卷积的式子.但是我们可以注意到前面具有组合数,如果拆成阶乘会很大,在模意义下你无法判断 ...

  9. Tarjan求强连通分量,缩点,割点

    Tarjan算法是由美国著名计算机专家发明的,其主要特点就是可以求强连通分量和缩点·割点. 而强联通分量便是在一个图中如果有一个子图,且这个子图中所有的点都可以相互到达,这个子图便是一个强连通分量,并 ...

  10. [洛谷P4147] 玉蟾宫

    类型:单调栈 传送门:>Here< 题意:求一个$01$矩阵中最大子矩形(全是$1$)的面积 解题思路 单调栈的一个经典应用 考虑维护一个数组$p[i][j]$表示$(i,j)$往上最多有 ...