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;
}

浙公网安备 33010602011771号