zoukankan      html  css  js  c++  java
  • 洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    洛谷P1823 [COI2007] Patrik 音乐会的等待(单调栈+二分查找)

    标签:题解
    阅读体验:https://zybuluo.com/Junlier/note/1333275

    这个题不是很难,但是没有转过来还是难想的
    可以先去做一下这个题:洛谷P1901 发射站
    蒟蒻发现很多题解都是错的呀,复杂度比较玄学吧
    介绍一种标准的(O(nlogn))的方法

    单调栈

    我们对于一个人作为方案中右边那个人时我们算答案(为了不算重)
    有哪些人我们看不到呢,无非是被它右边的人挡住了是吧
    那么从左往右维护一个单调递减的单调栈,单调栈中的人不会出现被挡住的情况(只有(i)看不到的情况后面会讲)
    自己想一下这里很简单

    二分查找

    考虑肯定只有单调栈中的人会被(i)算入答案是吧
    并且很容易发现一定是个连续的区间([x,i-1])这不废话吗
    那么我们在单调栈中二分这个区间的左端点,显然左端点就是(i)左边第一个比(i)高的数
    这不就是上面那个发射站的题目了吗
    计入答案的就是区间长度啦

    代码极其简单。。。

    #include<bits/stdc++.h>
    #define il inline
    #define rg register
    #define ldb double
    #define lst long long
    #define rgt register int
    #define N 500050
    using namespace std;
    const int Inf=1e9;
    il int read()
    {
    	int s=0,m=0;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')m=1;ch=getchar();}
    	while( isdigit(ch))s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
    	return m?-s:s;
    }
    
    int n,top;lst Ans;
    int H[N],stk[N];
    
    il void Calc(rgt x)
    {
    	rgt le=0,ri=top,mid,ret=0;
    	while(le<=ri)
    	{
    		mid=(le+ri)>>1;
    		if(H[stk[mid]]>x)ret=mid,le=mid+1;
    		else ri=mid-1;
    	}
    	if(!ret)Ans+=top;
    	else Ans+=top-ret+1;
    }
    int main()
    {
    	n=read();
    	for(rgt i=1;i<=n;++i)H[i]=read();
    	for(rgt i=1;i<=n;++i)
    	{
    		Calc(H[i]);
    		while(top>0&&H[i]>H[stk[top]])--top;
    		stk[++top]=i;
    	}return printf("%lld
    ",Ans),0;
    }
    
  • 相关阅读:
    JVM字节码-字节码进阶
    JVM字节码-Class文件结构
    CT03 Contest#10 equation 大力打表+讨论
    2021CT03 Contest#9 降智场
    妙妙题 noi.ac 2323 Connecting
    洛谷 P4774 [NOI2018] 屠龙勇士
    [模板] 扩展中国剩余定理
    洛谷 P1082 [NOIP2012 提高组] 同余方程
    洛谷 P1516 青蛙的约会
    2021牛客暑期多校训练营3 Kuriyama Mirai and Exclusive Or
  • 原文地址:https://www.cnblogs.com/cjoierljl/p/9912127.html
Copyright © 2011-2022 走看看