Luogu P4392 [BOI2007]Sound 静音问题


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;
}

猜你喜欢

转载自www.cnblogs.com/Hawking-llfz/p/11599627.html