洛谷P2471——[SCOI2007]降雨量

本机AC提交RE……

传送门:QAQQAQ

题意:自己看

思路:据说这道题用RMQ做很快,但这道题线段树是可以的

线段树维护一段区间最左年,最右年,是否有间隙和区间最大值

这道题分类讨论是一大难点,主要分为以下几种情况:

1.AB均不确定,输出maybe

2.A确定B不确定:

  若A是A到B最大的,输出maybe

  否则输出false

3.A不确定B确定:

  若B是lower_bound(A)到B最大的,则输出maybe

  否则输出false

4.A确定B确定

  若B是A+1到B最大的,A是A到B最大的,且之间没有间隙,输出true

  若满足上述条件,但有间隙,则输出maybe

  否则输出false

在代码实现方面,我先是没有考虑“严格小于”这一条件,认为最大值等于B就行了,而没有判断之前有无相等

然后加了一些特判防止自己玄学线段树越界停不下来。。。(最近代码实现能力有待提升啊。。。)

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
  
int n;
struct node
{
    int ly,ry,max_r,Gap;
}tree[N*4];
int rain[N],year[N];
  
void push_up(node& fa,node ls,node rs)
{
    fa.ly=ls.ly;
    fa.ry=rs.ry;
    fa.max_r=max(ls.max_r,rs.max_r);
    fa.Gap=0;
    if(ls.Gap||rs.Gap) fa.Gap=1;
    if(ls.ry+1<rs.ly) fa.Gap=1;
}
  
void build(int x,int l,int r)
{
    if(l==r)
    {
        tree[x].ly=year[l];
        tree[x].ry=year[l];
        tree[x].max_r=rain[l];
        tree[x].Gap=0;
        return;
    }
    int mid=(l+r)>>1;
    build(x+x,l,mid);
    build(x+x+1,mid+1,r);
    push_up(tree[x],tree[x+x],tree[x+x+1]);
}
  
node query(int x,int l,int r,int L,int R)
{
    node ret;
    if(L<=l&&R>=r) return tree[x];
    int mid=(l+r)>>1;
    if(mid<L) return query(x+x+1,mid+1,r,L,R);
    if(mid>=R) return query(x+x,l,mid,L,R);
    node ls=query(x+x,l,mid,L,R);
    node rs=query(x+x+1,mid+1,r,L,R);
    push_up(ret,ls,rs);
    return ret;
}
  
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&year[i],&rain[i]);
    build(1,1,n);
    int q; scanf("%d",&q);
    while(q--)
    {
        int x,y,xx,yy,bl=0;
        scanf("%d%d",&xx,&yy);
        if(yy<xx)
        {
            puts("false");
            continue;
        }
        if(xx==yy) 
        {
            puts("maybe");
            continue;
        }
        x=lower_bound(year+1,year+n+1,xx)-year;
        y=lower_bound(year+1,year+n+1,yy)-year;
        if(xx!=year[x]&&yy!=year[y]) puts("maybe");
        else if(xx!=year[x])
        {
            if(y==1||x==y) puts("maybe");
            else
            {
                node n1=query(1,1,n,x,y);
                node n2=query(1,1,n,x,y-1);
                //中间降雨量必须严格小于! 
                if(n1.max_r==rain[y]&&n2.max_r<rain[y]) puts("maybe");
                else puts("false");
            }
        }
        else if(yy!=year[y])
        {
            if(x==n||x==y-1) puts("maybe");
            else
            {
                node n1=query(1,1,n,x,y-1);
                node n2=query(1,1,n,x+1,y-1);
                if(n1.max_r==rain[x]&&n2.max_r<rain[x]) puts("maybe");
                else puts("false");
            }
        }
        else
        {
            if(x+1==y)
            {
                if(rain[x]<rain[y]) puts("false");
                else if(year[x]+1==year[y]) puts("true");
                else puts("maybe");
                continue;//之前没写continue啊啊啊。。。 
            }//特判防止线段树越界 
            node n1=query(1,1,n,x,y);
            node n2=query(1,1,n,x+1,y);
            node n3=query(1,1,n,x+1,y-1);
            if(n2.max_r==rain[y]&&rain[y]<=rain[x]&&n3.max_r<rain[y])
            {
                if(n1.Gap) puts("maybe");
                else puts("true");
            }
            else puts("false");
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Forever-666/p/11210715.html