首页 > 其他分享 >P1823

P1823

时间:2024-11-16 21:20:47浏览次数:1  
标签:10 le int ll 统计 单调 P1823

[COI2007] Patrik 音乐会的等待

题目描述

\(n\) 个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。

队列中任意两个人 \(a\) 和 \(b\),如果他们是相邻或他们之间没有人比 \(a\) 或 \(b\) 高,那么他们是可以互相看得见的。

写一个程序计算出有多少对人可以互相看见。

数据规模与约定

对于全部的测试点,保证 \(1\le\) 每个人的高度 \(< 2^{31}\),\(1 \le n \le 5\times 10^5\)。


身为一个普及组选手,对单调栈的利用展现出了普及组的水准,致敬传奇普及老哥 cfm

对于序列上点对统计的问题,一般都是以右端点为计数标准,统计有多少个合法的左端点。这道题也一样:对于 \(b\) 统计有多少 \(a(a<b)\) 使得 \(\max\limits_{j = a+1}^{b - 1}h_j \le \min\{h_a, h_b\}\)

这个式子不好做,把右边拆开讨论一下。

  1. \(h_a > h_b\),即 \(\max\limits_{j = a + 1}^{b-1}h_j < h_b\)。此时显然 \(a\) 只能是“第一个在 \(b\) 之前且大于 \(b\) 的位置”,容易单调栈出来。
  2. \(h_a < h_b\)。类似的思考会发现这样的 \(a\) 就会被 \(b\) 给“堵住”,从而让 \(b\) 之后的看不到,那么我们只需要针对 \(b\) 单独统计即可。具体可以利用单调栈。
  3. \(h_a = h_b\)。在顶统计一次,然后将其合并。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 5e5;
int a[N + 10], c[N + 10], b[N + 10];
struct node {
	int val, cnt;
};
int bk[N + 10], fr[N + 10], n;
stack <node> sta;

int main() {
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	
	ll sum = 0;
	for(int i = 1; i <= n; i++) {
		node tmp = (node){a[i], 1};
		while(!sta.empty() && sta.top().val <= a[i]) {
			if(sta.top().val == a[i]) tmp.cnt += sta.top().cnt;
			sum += sta.top().cnt;
			sta.pop();
		}
		if(!sta.empty()) sum++;
		sta.push(tmp);
	}
	
	cout << sum << endl;
}

标签:10,le,int,ll,统计,单调,P1823
From: https://www.cnblogs.com/thirty-two/p/18549834

相关文章

  • 单调栈(P1823 [COI2007] Patrik 音乐会的等待)
    [COI2007]Patrik音乐会的等待题目描述\(n\)个人正在排队进入一个音乐会。人们等得很无聊,于是他们开始转来转去,想在队伍里寻找自己的熟人。队列中任意两个人\(a\)和......
  • P1823 [COI2007] Patrik 音乐会的等待
    用单调队列维护即可,注意要考虑高度相同的情况(可以记录单调队列中相同的个数)。时间复杂度为\(O(n)\)。#include<bits/stdc++.h>usingnamespacestd;#defineintlong......