发射站
题目描述
某地有 N N N 个能量发射站排成一行,每个发射站 i i i 都有不相同的高度 H i H_i Hi,并能向两边(两端的发射站只能向一边)同时发射能量值为 V i V_i Vi 的能量,发出的能量只被两边最近的且比它高的发射站接收。显然,每个发射站发来的能量有可能被 0 0 0 或 1 1 1 或 2 2 2 个其他发射站所接受。
请计算出接收最多能量的发射站接收的能量是多少。
输入格式
第 1 1 1 行一个整数 N N N。
第 2 2 2 到 N + 1 N+1 N+1 行,第 i + 1 i+1 i+1 行有两个整数 H i H_i Hi 和 V i V_i Vi,表示第 i i i 个发射站的高度和发射的能量值。
输出格式
输出仅一行,表示接收最多能量的发射站接收到的能量值。答案不超过 32 位带符号整数的表示范围。
样例 #1
样例输入 #1
3
4 2
3 5
6 10
样例输出 #1
7
提示
对于 40 % 40\% 40% 的数据, 1 ≤ N ≤ 5000 , 1 ≤ H i ≤ 1 0 5 , 1 ≤ V i ≤ 1 0 4 1\le N\le 5000,1\le H_i\le 10^5,1\le V_i\le 10^4 1≤N≤5000,1≤Hi≤105,1≤Vi≤104。
对于 70 % 70\% 70% 的数据, 1 ≤ N ≤ 1 0 5 , 1 ≤ H i ≤ 2 × 1 0 9 , 1 ≤ V i ≤ 1 0 4 1\le N\le 10^5,1\le H_i\le 2\times 10^9,1\le V_i\le 10^4 1≤N≤105,1≤Hi≤2×109,1≤Vi≤104。
对于 100 % 100\% 100% 的数据, 1 ≤ N ≤ 1 0 6 , 1 ≤ H i ≤ 2 × 1 0 9 , 1 ≤ V i ≤ 1 0 4 1\le N\le 10^6,1\le H_i\le 2\times 10^9,1\le V_i\le 10^4 1≤N≤106,1≤Hi≤2×109,1≤Vi≤104。
我们正常的思路就是直接模拟
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e+6 + 5;
int n;
ll h[N];
int v[N];
int ans[N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i] >> v[i];
}
h[0] = h[n+1] = 2000000000;
for (int i = 1;i<=n; i++) {
for (int j = i - 1; j > 0; j--) {
if (h[j] > h[i]) {
ans[j] += v[i];
break;
}
}
for (int j = i + 1; j <= n; j++) {
if (h[j] > h[i]) {
ans[j] += v[i];
break;
}
}
}
int pp = 0;
for (int i = 1; i <= n; i++) {
pp = max(ans[i], pp);
}
cout << pp;
return 0;
}
超时了两个点
我们需要维护一个单调栈
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e+6 + 5;
int n;
ll h[N];
int v[N];
int ans[N];
int q[N];
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> h[i] >> v[i];
}
int top = 0; // 这是一个栈顶的
for (int i = 1; i <= n; i++) {
while (top && h[q[top]] < h[i]) // 出栈操作,这个必须保证里面有东西,且栈顶的是最小的, 如果进来的大于栈顶的,那么这个就要出栈
{
ans[i] += v[q[top--]];
}
// 进栈操作
q[++top] = i;
ans[q[top - 1]] += v[i]; // 给最近一个高的加上去
}
int pp = 0;
for (int i = 1; i <= n; i++) {
pp = max(pp, ans[i]);
}
cout << pp;
return 0;
}
求m区间内的最小值
题目描述
一个含有 n n n 项的数列,求出每一项前的 m m m 个数到它这个区间内的最小值。若前面的数不足 m m m 项则从第 1 1 1 个数开始,若前面没有数则输出 0 0 0。
输入格式
第一行两个整数,分别表示 n n n, m m m。
第二行, n n n 个正整数,为所给定的数列 a i a_i ai。
输出格式
n n n 行,每行一个整数,第 i i i 个数为序列中 a i a_i ai 之前 m m m 个数的最小值。
样例 #1
样例输入 #1
6 2
7 8 1 4 3 2
样例输出 #1
0
7
7
1
1
3
提示
对于 100 % 100\% 100% 的数据,保证 1 ≤ m ≤ n ≤ 2 × 1 0 6 1\le m\le n\le2\times10^6 1≤m≤n≤2×106, 1 ≤ a i ≤ 3 × 1 0 7 1\le a_i\le3\times10^7 1≤ai≤3×107。
#include<iostream>
#include<cstdio>
const int N = 2000005;
int n, m;
int a[N];
int f[N];
int main() {
int top = 0;
int di = 1;
scanf("%d%d", &n, &m);
printf("0\n");
f[++top] = 1;
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
if (i >= 2) {
// 出栈,先排除不在区间内的
while (i - f[di] > m) {
di++;
}
printf("%d\n", a[f[di]]);
// 先进栈
while (a[f[top]] >= a[i] && top >= di)
{
top--;
}
f[++top] = i;
}
}
return 0;
}
用现成的工具
deque
operator[];//返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据
push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据
每日温度
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& temperatures) {
int len = temperatures.size();
deque<int> p;
vector<int> ans(len);
for (int i = 0; i < len; i++) {
int temp = temperatures[i];
while (p.size() && temp > temperatures[p.back()]) {
int po = p.back();
cout << "尾巴的 " << po << endl;
p.pop_back();
ans[po] = i - po;
}
p.push_back(i);
}
return ans;
}
};
leecode 1475
class Solution {
public:
vector<int> finalPrices(vector<int>& prices) {
int len = prices.size();
vector<int> ans(len);
deque<int> q;
for (int i = 0; i < len; i++) {
int now = prices[i];
while (q.size()&&now<=prices[q.back()])
{
int pos = q.back();
q.pop_back();
ans[pos] = prices[pos] - now;
}
q.push_back(i);
}
// 别忘记这一步
while(q.size()){
int pos = q.back();
ans[pos] = prices[pos];
q.pop_back();
}
return ans;
}
};
落谷2422
我们还要注意退出for循环后的边界处理,这时候单调栈里面还有东西
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5;
int a[N];
int n;
int ans = 0;
int p[N];
int l[N], r[N];
signed main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i];
p[i] = p[i - 1] + a[i];
l[i] = r[i] = i;
}
deque<int> q;
for (int i = 1; i <= n; i++) {
int now = a[i];
while (q.size()&& now<a[q.back()])
{
int u = q.back();
q.pop_back();
r[u] = i;
}
q.push_back(i);
}
while (q.size()) {
int u = q.back();
q.pop_back();
r[u] = n+1;
}
q.clear();
for (int i = n; i >= 1; i--) {
int now = a[i];
while (q.size() && now < a[q.back()]) {
int u = q.back();
q.pop_back();
l[u] = i;
}
q.push_back(i);
}
while (q.size())
{
int u = q.back();
q.pop_back();
l[u] = 0;
}
for (int i = 1; i <= n; i++) {
ans = max(ans, a[i] * (p[r[i]-1] - p[l[i]]));
}
//for (int i = 1; i <= n; i++) {
// cout << l[i] << " " << r[i] << endl;
//}
cout << ans;
return 0;
}