[bzoj] 1067: [SCOI2007]降雨量

这道题也是够了,我调了好几个小时。。

条件判断实在烦,设从x年到y年:

maybe:①x,y未知

②x知y未知,因为y最大与x等,区间中已知没有大于x的

③y知x未知,区间中已知没有大于y的

④x,y都知,且x>=y,区间中已知没有大于y的,但x到y此区间中有未知年份

⑤x,y在边界

true:x,y都知,且x>=y,区间中已知没有大于y的,但x到y此区间中没有未知年份

其余的都是false

用线段树维护最大值,顺带记录这一段中已知的年份个数

膜拜一遍过的神犇


#include <cstdio>
#define ls (k<<1)
#define rs (ls|1)
using namespace std;
int n,m,x,y,nx,ny;
int may=-1000000000,miy=1000000000;
bool kk=0;
int kx,ky;
const int N=200000;
struct peace{
    bool f;
    int l,r,ma,size;
}tr[262144];
inline int max(int l,int r)
{
    return l>r?l:r;
}
int getnum(int k,int x)
{
    if (tr[k].l==tr[k].r)
    {
        if (tr[k].l==x) return tr[k].ma;
        else
        {
            kk=1;
            return 0;
        }
    }
    if (x<=tr[ls].r) return getnum(ls,x);
    else if (x>=tr[rs].l) return getnum(rs,x);
    return 0;
}
 
void build_tr(int k,int l,int r)
{
    if (l==r) 
    {
        scanf("%d %d",&tr[k].l,&tr[k].ma);
        may=max(tr[k].l,may);
        if (miy>tr[k].l) miy=tr[k].l;
        tr[k].r=tr[k].l;
        tr[k].f=1;
        tr[k].size=1;
        return; 
    }
    int mid=(l+r)/2;
    build_tr(ls,l,mid),build_tr(rs,mid+1,r);
    if (tr[ls].f&&tr[rs].f) tr[k].f=1;
    if (tr[ls].r+1!=tr[rs].l) tr[k].f=0;
    tr[k].l=tr[ls].l;tr[k].r=tr[rs].r;
    tr[k].ma=max(tr[ls].ma,tr[rs].ma);
    tr[k].size=tr[ls].size+tr[rs].size;
    return ;
}
 
int querysize(int k,int ql,int qr)
{
    if(qr<tr[k].l||ql>tr[k].r) return 0;
    if(qr>=tr[k].r&&ql<=tr[k].l) return tr[k].size;
    return querysize(ls,ql,qr)+querysize(rs,ql,qr);
}
 
int ask(int k,int l,int r)
{
    if (r<tr[k].l||l>tr[k].r) return 0;
    if (l<=tr[k].l&&tr[k].r<=r)
    {
        if (!tr[k].f) kk=1;
        return tr[k].ma;
    }
    return max(ask(ls,l,r),ask(rs,l,r));
    return 0;
}
int main()
{
    register int i;
    scanf("%d",&n);
         may=-1000000000,miy=1000000000;
    build_tr(1,1,n);
    scanf("%d",&m);
    for (i=1;i<=m;i++)
    {
        scanf("%d %d",&x,&y);
        if (y<x)
        {
            printf("false");
            continue;
        }
        kx=x+1;
        ky=y-1;
        nx=getnum(1,x);ny=getnum(1,y);
        if (!nx&&!ny)
        {
            printf("maybe\n");
            continue;
        }
        if (x==may||y==miy) 
        {
            printf("maybe\n");
            continue;
        }
        if (!ny)
        {
            int q=ask(1,kx,ky);
            if (q>=nx) printf("false\n");
            else printf("maybe\n");
        }
        if (!nx)
        {
            int q=ask(1,kx,ky);
            if (q>=ny) printf("false\n");
            else printf("maybe\n");
        }
        if (nx&&ny)
        {
            if (ny>nx) printf("false\n");
            else
            {
                int q=ask(1,kx,ky);
                if (q>=ny) printf("false\n");
                else if (querysize(1,kx,ky)==ky-kx+1) printf("true\n");
                else printf("maybe\n");
            }
        }
    }
        return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值