BZOJ 4491 分块OR差分+线段树
2024-10-01 04:40:41
思路:
(是不是只有我作大死写了个分块)
up[i][j]表示从第i块开始到第j个位置 上升的最大值
down[i][j]同理
left_up[i]表示从第i块开始能够上升的最长长度
left_down[i]同理
right_up[i]表示从第i块结尾上升的最长长度
right_down[i]同理
然后就是各种恶心的分类讨论
(见代码吧,,,,,,)
嗯这道题还可以差分以后线段树维护>0的最长长度(左max 右max 区间max)
//By SiriusRen
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=,inf=0x3f3f3f3f;
int n,q,l,r,a[N],block[N],up[][N],down[][N],left_up[],left_down[],right_up[],right_down[];
int main(){
scanf("%d",&n);int Block=sqrt(n);
for(int i=;i<=n;i++)scanf("%d",&a[i]);
for(int i=;i<=n;i++)block[i]=(i-)/Block+;
for(int i=;i<=block[n];i++){
int temp_up=,temp_down=,f_up=,f_down=;
for(int j=lower_bound(block+,block++n,i)-block;j<=n;j++){
up[i][j]=max(up[i][j-],temp_up),down[i][j]=max(temp_down,down[i][j-]);
if(!f_down)left_down[i]=temp_down;
if(!f_up)left_up[i]=temp_up;
if(a[j+]>a[j])temp_up++,temp_down=,f_down=;
else if(a[j+]<a[j])temp_down++,temp_up=,f_up=;
else temp_up++,temp_down++;
}
}
for(int i=;i<=block[n];i++){
int temp=lower_bound(block+,block++n,i)-block,j=upper_bound(block+,block++n,i)-block-,temp_up=,temp_down=;
for(;block[j]==block[temp];j--){
right_up[i]=max(right_up[i],temp_up),right_down[i]=max(right_down[i],temp_down);
if(a[j-]>a[j])temp_up++,temp_down=-inf;
else if(a[j-]<a[j])temp_down++,temp_up=-inf;
else temp_up++,temp_down++;
}
}
scanf("%d",&q);
while(q--){
scanf("%d%d",&l,&r);
if(block[l]==block[r]){
int ans=;
int temp_up=,temp_down=;
for(int j=l;j<=r;j++){
ans=max(ans,max(temp_up,temp_down));
if(a[j+]>a[j])temp_up++,temp_down=;
else if(a[j+]<a[j])temp_down++,temp_up=;
else temp_up++,temp_down++;
}
printf("%d\n",ans);
}
else{
int L=block[l]+,ans=max(up[L][r],down[L][r]),temp_up=,temp_down=;
int beginL=lower_bound(block+,block++n,L)-block;
for(int j=l;j<beginL;j++){
ans=max(ans,max(temp_up,temp_down));
if(a[j+]>a[j])temp_up++,temp_down=;
else if(a[j+]<a[j])temp_down++,temp_up=;
else temp_up++,temp_down++;
}
if(a[beginL]>=a[beginL-]){
int tmpx=min(right_down[L-],beginL-l),tmpy=min(r-beginL+,left_up[L]);
ans=max(ans,tmpx+tmpy);
}
if(a[beginL]<=a[beginL-]){
int tmpx=min(right_up[L-],beginL-l),tmpy=min(r-beginL+,left_down[L]);
ans=max(ans,tmpx+tmpy);
}
printf("%d\n",ans);
}
}
}
最新文章
- css外边距margin
- iReport 下载地址
- iOS学习10之OC类和对象
- 【AT91SAM3S】建立基于SAM3S库的工程并点亮LED
- Leetcode#129 Sum Root to Leaf Numbers
- php使用phpmailer发送邮件
- [LeetCode] 30. Substring with Concatenation of All Words 解题思路 - Java
- Sublime 学习记录(三) Emmet 插件
- PHP使用文件流下载文件方法(附:解决下载文件内容乱码问题)
- postgresql 添加uuid扩展
- C#的Lock
- XMind 8 pro update 7激活方法
- Linux在VirtualBox的网络设置
- 图论分支-Tarjan初步-割点和割边
- DroneCI启用privileged
- Responsive响应式设计
- 什么叫做GNU
- 〖Windows〗三星(SAMSUNG)905S3G-K07 安装Windows 7 过程分享
- [LeetCode] 383. Ransom Note_Easy tag: Hash Table
- xshell评估过期解决办法