P8037 [COCI2015-2016#7] Prokletnik
提供一种树状数组的解法。
题目链接。
题意简述
一个好区间定义为:这个区间的两个端点值为整个区间的最大值和最小值。
有一段长为
求出
题目分析
套路地,我们可以离线,按照右端点排序。那么类似增量法,每次加入一个
一开始的想法:单调栈预处理出向左 / 向右第一个大于 / 小于的位置,然后二维偏序,对于当前的
首先令右端点的值为最大值,相反的将每个
具体实现如下:
- 维护一个树状数组
,表示对应的栈中的元素作为左端点时的最大右端点,维护前缀最大值。 - 维护一个树状数组
,表示 节点为左端点的最大答案,维护后缀最大值。 - 每一次要加入当前的
,将栈中不再会被更新的元素弹掉,并将其答案R.query(top)-st[top]+1
加入到 中。 - 然后将
入栈,二分找到栈中的第一个合法位置,并修改 和 。由于 维护的是前缀最值,修改是改其后面的部分,故栈中所有要被更新的左端点都被更新了。 - 处理询问时,令栈中第一个大于等于当前询问的位置为
。由于我们先前更新时对于 的更新时没有全部都更新到 上去的,那么更新答案要对 的最值和 的答案R.query(it) - st[it] + 1
取一个最大值,类似于一个延迟更新。
时间复杂度
CODE
#include<bits/stdc++.h>
#define debug() cerr<<"Line:"<<__LINE__<<endl
using namespace std;
typedef pair<int,int> pii;
const int N = 500010;
int n,a[N],res[N],q;
vector<pii> e[N];
int st[N],top;
int l[N];
template <int op = 1>
struct Bit{
int c[N];
#define lowbit(a) (a&(-a))
void init(){
memset(c,0,sizeof c);
}
void add(int x,int v){
for(int i = x;0 < i && i <= n;i += op * lowbit(i))c[i] = max(c[i],v);
}
int query(int x){
int res = 0;
for(int i = x;0 < i && i <= n;i -= op * lowbit(i))res = max(c[i],res);
return res;
}
};
Bit<1> R;
Bit<-1> ans;
void solve(){
R.init(),ans.init();
top = 0;
for(int i = 1;i<=n;++i){
while(top && a[st[top]] <= a[i])--top;
l[i] = st[top]+1;
st[++top] = i;
}
top = 0;
for(int i = 1;i<=n;++i){
while(top && a[st[top]] > a[i]){
int res = R.query(top) - st[top] + 1;
ans.add(st[top],res);
--top;
}
st[++top] = i;
int it = lower_bound(st+1,st+top+1,l[i])-st;
R.add(it,i), ans.add(st[it],i-st[it]+1);
for(pii p : e[i]){
int it = lower_bound(st+1,st+top+1,p.first)-st;
int fi = ans.query(p.first), se = R.query(it) - st[it] + 1;
res[p.second] = max(res[p.second],max(fi,se));
}
}
}
//#define printf printf(">>>> "),printf
int main(){
scanf("%d",&n); for(int i = 1;i<=n;++i)scanf("%d",&a[i]);
scanf("%d",&q); for(int i = 1,l,r;i<=q;++i){
scanf("%d%d",&l,&r);
e[r].push_back({l,i});
}
solve();
for(int i = 1;i<=n;++i)a[i] = -a[i];
solve();
for(int i = 1;i<=q;++i)printf("%d\n",res[i]);
return 0;
}
反思 & 总结
trick:
- 离线按右端点排序是处理区间问题;
- 对于两个性质相反的东西进行统计可以把所有数取反再跑一遍;
- 用树状数组维护栈。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】