版权声明:小蒟蒻的博客转载也请注明出处哦 https://blog.csdn.net/qq_42835823/article/details/86656405
【雪地】
先预处理出一次滑行i的鞋子最少需要的厚度是多少, 查询即可。
考虑将雪地高度从小到大加入,每次把当前所在的区间切成两个区间,查询一下最大的区间,与原来的取 即可。
为什么要用
?
因为
自动从小到大排序,且支持插入和删除。
(内含一个暴力程序)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
const int N=1e5+5;
int n,m,a[N],mx=0;
int check(int s,int d){
int f=0;
for(int i=1;i<=n;i++){
if(a[i]>s)f++;
else f=0;
if(f>=d)return 0;
}
return 1;
}
void work_1(){
for(int i=1;i<=n;i++){
a[i]=read();
mx=(a[i]>mx)?a[i]:mx;
}
while(m--){
int s,d;
s=read();d=read();
if(s>=mx){printf("1\n");continue;}
printf("%d\n",check(s,d));
}
}
struct node{
int hei,pos;
}b[N];
inline bool Sort(const node &x,const node &y){
return x.hei<y.hei;
}
int d[N],r[N];//右端点的左端点
set<int>sr;//右端点
multiset<int>sl;//slen 区间长度
void work_2(){
memset(d,0x3f,sizeof(d));
for(int i=1;i<=n;i++){
b[i].hei=read();
b[i].pos=i;
}
sort(b+1,b+n+1,Sort);
r[n]=1;d[n-1]=0;
sr.insert(n);sl.insert(1-n);//用负数变成从大到小排序
for(int i=1;i<=n;i++){
int h=b[i].hei,x=b[i].pos;
int v=*sr.lower_bound(x);//找到所在区间
int u=r[v];
r[v]=x;r[x]=u;//拆成两个区间
sr.insert(x);//插入新的右端点
sl.erase(sl.find(u-v));//删除原来长度
sl.insert(u-x);sl.insert(x-v);//插入新长度
u=*sl.begin();u=-u;//找最大
d[u]=min(d[u],h);//更新答案
}
for(int i=1;i<n;i++)
if(d[i]==0x3f3f3f3f)d[i]=d[i-1];//有些d[i]可能没算到,更新一下
while(m--){
int s,k;
s=read();k=read();
if(s>=d[k])printf("1\n");//O(1)查询
else printf("0\n");
}
}
int main(){
n=read();m=read();
if(n<=1000&&m<=1000)work_1();//暴力
else work_2();//正解
return 0;
}