Luogu P4392 [BOI2007]Sound 静音问题
解析
- 挺简单的一道线段树题目,区间长度已经给定,只需用线段树处理区间最大、最小值,然后枚举区间左端点,判断这段区间是否合法即可
Code
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int N=1e6+5;
int n,m,c,h[N];
bool flag;
struct Tree
{
struct tree
{
int minn,maxx;
}tr[N<<2];
void pushup(int root)
{
tr[root].minn=min(tr[root*2].minn,tr[root*2+1].minn);
tr[root].maxx=max(tr[root*2].maxx,tr[root*2+1].maxx);
return;
}
void build(int root,int l,int r)
{
if(l==r)
{
tr[root].minn=tr[root].maxx=h[l];
return;
}
int mid=(l+r)>>1;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
pushup(root);
return;
}
int query(int root,int l,int r,int ll,int rr,int fag)
{
if(ll<=l&&r<=rr)
{
if(fag==1) return tr[root].minn;
else return tr[root].maxx;
}
int mid=(l+r)>>1;
if(mid>=rr) return query(root*2,l,mid,ll,rr,fag);
else
{
if(mid<ll) return query(root*2+1,mid+1,r,ll,rr,fag);
else
{
if(fag==1) return min(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
else return max(query(root*2,l,mid,ll,mid,fag),query(root*2+1,mid+1,r,mid+1,rr,fag));
}
}
}
}str;
bool check(int x)
{
int mins=str.query(1,1,n,x,x+m-1,1);
int maxs=str.query(1,1,n,x,x+m-1,2);
return (maxs-mins<=c)?1:0;
}
int main()
{
scanf("%d%d%d",&n,&m,&c);
for(int i=1;i<=n;i++) scanf("%d",&h[i]);
str.build(1,1,n);
for(int i=1;i<=n-m+1;i++)
{
if(check(i))
{
flag=1;
printf("%d\n",i);
}
}
if(!flag) puts("NONE");
return 0;
}
原文地址:https://www.cnblogs.com/Hawking-llfz/p/11599627.html
时间: 2024-10-04 12:29:55