P10174题解
P10174 Great Segments
题解
个人感觉这是最简单的一题。
考虑什么区间是好的,发现条件等价于从后往前维护单调栈,那么到 \(i\) 时,从 \(i\) 到单调栈前 \(k-1\) 个位置的区间均合法,更一般的,记 \(nxt_i\) 表示满足 \(i<j,a_i<a_j\) 的最小的 \(j\),那么就是 \(nxt\) 嵌套 \(k-1\) 遍。
这种询问方式不难想到差分,那么左端点是好维护的,右端点的话,我们把每个点的 \(nxt\) 视作一条边,则构成了一棵树,我们需要支持多次树链加,单次查询,树上差分即可。
代码:
/*
* @Author: operator_
* @Date: 2024-02-18 14:48:19
* @Last Modified by: operator_
* @Last Modified time: 2024-02-18 17:14:52
*/
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int rd() {
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,k,a[1000005],st[1000005],top,fa[1000005],d1[1000005],d2[1000005];
int h[1000005],cnt;
struct QWQ{int v,nxt;} e[1000005*2];
void add(int u,int v) {e[++cnt]={v,h[u]},h[u]=cnt;}
void dfs(int u) {
for(int i=h[u];i;i=e[i].nxt)
dfs(e[i].v),d2[u]+=d2[e[i].v];
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) a[i]=rd();
for(int i=n;i>=1;i--) {
while(top&&a[st[top]]<a[i]) top--;
fa[i]=st[top],add(fa[i],i),st[++top]=i;
d1[i]+=min(top,k)-1;
d2[fa[i]]--,d2[fa[st[top+1-min(top,k)]]]++;
}
dfs(0);
for(int i=1;i<=n;i++) d1[i+1]+=d2[i];
for(int i=1;i<=n;i++) {
d1[i]+=d1[i-1];
printf("%lld\n",d1[i]);
}
return 0;
}
本文来自博客园,作者:operator,转载请注明原文链接:https://www.cnblogs.com/operator-/p/18019855 ♪(^∀^●)ノシ