P8251 [NOI Online 2022 提高组] 丹钓战

讲个笑话,这道题目我本来是在扫描线的题目里边找到的,但我的方法跟扫描线没有任何关系。

题意不多说了。

发现题目谐音单调栈,但是并没有什么帮助,因为题干在描述的不就是一个单调栈嘛?

不可否定的,对于 \([L,R]\),一个个位置 \(A[L]\) 一定是成功的。

我们只需要判断什么时候会把 \(A[L]\) 给弹出去,这个位置就是下一个成功的。

对于下一个,这依然是一个相同的问题罢了。

我们要做的工作实际上就是一直跳。

用倍增优化一下就好了,\(O(nlogn)\)

就没有了。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MN=1e6+115;
int dp[MN][20], stk[MN], top;
int n, q, a[MN], b[MN];
signed main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	cin>>n>>q;
	for(int i=1; i<=n; ++i) cin>>a[i];
	for(int i=1; i<=n; ++i) cin>>b[i];
	for(int i=1; i<=n; ++i){
		while(top&&((a[i]==a[stk[top]])||(b[i]>=b[stk[top]]))){
			dp[stk[top]][0]=i; --top;
		}
		stk[++top]=i;
	}
	for(int j=1; j<20; ++j){
		for(int i=1; i<=n; ++i){
			dp[i][j]=dp[dp[i][j-1]][j-1];
		}
	}
	for(int j=1; j<=q; ++j){
		int ans=0, l, r;
		cin>>l>>r;
		for(int i=19; i>=0; --i){
			if(dp[l][i]&&dp[l][i]<=r){
				ans+=1<<i; l=dp[l][i];
			}
		}
		cout<<ans+1<<'\n';
	}

	return 0;
}
posted @ 2025-09-08 18:41  BaiBaiShaFeng  阅读(7)  评论(0)    收藏  举报
Sakana Widget右下角定位