【bzoj1067】[SCOI2007]降雨量

[SCOI2007]降雨量

Description

  我们常常会说这样的话:“X年是自Y年以来降雨量最多的”。它的含义是X年的降雨量不超过Y年,且对于任意
Y<Z<X,Z年的降雨量严格小于X年。例如2002,2003,2004和2005年的降雨量分别为4920,5901,2832和3890,
则可以说“2005年是自2003年以来最多的”,但不能说“2005年是自2002年以来最多的”由于有些年份的降雨量未
知,有的说法是可能正确也可以不正确的。
Input

  输入仅一行包含一个正整数n,为已知的数据。以下n行每行两个整数yi和ri,为年份和降雨量,按照年份从小
到大排列,即yi<yi+1。下一行包含一个正整数m,为询问的次数。以下m行每行包含两个数Y和X,即询问“X年是
自Y年以来降雨量最多的。”这句话是必真、必假还是“有可能”。
Output

  对于每一个询问,输出true,false或者maybe。
Sample Input
6

2002 4920

2003 5901

2004 2832

2005 3890

2007 5609

2008 3024

5

2002 2005

2003 2005

2002 2007

2003 2007

2005 2008
Sample Output
false

true

false

maybe

false
HINT

100%的数据满足:1<=n<=50000, 1<=m<=10000, -10^9<=yi<=10^9, 1<=ri<=10^9

线段树+离散化。然后用了一个很高级的map。然后就询问。代码不长(也就170多行)。分享一个map的(http://blog.csdn.net/m__hd/article/details/52622162),代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
using namespace std;
map<int,int>mp;
struct node
{
    int x,k,q;
}a[51000];
int n,m,p,d[51000];
struct trnode
{
    int l,r,lc,rc,c;
    bool bk;
}tr[210000];int trlen;
void bt(int l,int r)
{
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;tr[now].c=0;
    tr[now].lc=tr[now].rc=-1;tr[now].bk=false;
    if(l<r)
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
    }
}
void change(int now,int p,int c)
{
    if(tr[now].l==tr[now].r){tr[now].c=c;tr[now].bk=true;return ;}
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    if(p<=mid)change(lc,p,c);
    else      change(rc,p,c);
    tr[now].c=max(tr[lc].c,tr[rc].c);
    if(tr[lc].bk==true&&tr[rc].bk==true)tr[now].bk=true;
}
int findmax(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r)return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    if(r<=mid)return findmax(lc,l,r);
    else if(mid+1<=l)return findmax(rc,l,r);
    else return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}
bool wen(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r){return tr[now].bk;}
    if(tr[now].l<=l&&r<=tr[now].r&&tr[now].bk==true)return true;
    int lc=tr[now].lc,rc=tr[now].rc;
    int mid=(tr[now].l+tr[now].r)/2;
    if(r<=mid)       return wen(lc,l,r);
    else if(mid+1<=l)return wen(rc,l,r);
    else return wen(lc,l,mid)&wen(rc,mid+1,r);
}
int cmp(const void *xx,const void *yy)
{
    node n1=*(node *)xx;
    node n2=*(node *)yy;
    return n1.x-n2.x;
}
void lisan()
{
    p=1;
    int fr=a[p].x;a[p].x=p;d[p]=a[p].k;
    mp.insert(pair<int,int>(fr,a[p].x));
    for(int i=2;i<=n;i++)
    {
        p++;
        if(a[i].x-1!=fr){d[p]=-1;p++;}
        fr=a[i].x;a[i].x=p;d[p]=a[i].k;
        mp.insert(pair<int,int>(fr,a[i].x));
    }
}
int erfenx(int x)
{
    int l=1,r=n,ab=99999999,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(x>a[mid].q)l=mid+1;
        else
        {
            if(ab>a[mid].q-x)
            {
                ab=a[mid].q-x;
                ans=a[mid].q;
            }
            r=mid-1;
        }
    }
    return mp[ans];
}
int erfeny(int y)
{
    int l=1,r=n,ab=99999999,ans;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(y>=a[mid].q)
        {
            if(ab>y-a[mid].q)
            {
                ab=y-a[mid].q;
                ans=a[mid].q;
            }
            l=mid+1;
        }
        else r=mid-1;
    }
    return mp[ans];
}
int main()
{
    scanf("%d",&n);int mmin,mmax;
    for(int i=1;i<=n;i++){scanf("%d%d",&a[i].x,&a[i].k);a[i].q=a[i].x;}
    qsort(a+1,n,sizeof(node),cmp);lisan();
    mmin=a[1].q;mmax=a[n].q;
    trlen=0;bt(1,p);
    for(int i=1;i<=n;i++)change(1,a[i].x,a[i].k);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        if(y<=mmin){printf("maybe\n");continue;}
        if(x>=mmax){printf("maybe\n");continue;}
        if(x+1==y)
        {
            if(mp[x]!=0&&mp[y]!=0)
            {
                    if(d[mp[x]]<d[mp[y]]){printf("false\n");continue;}
                    else {printf("true\n");continue;}
            }
            else printf("maybe\n");
            continue;
        }
        if(mp[x]!=0&&mp[y]!=0)
        {
            if(d[mp[x]]<d[mp[y]]){printf("false\n");continue;}
            int xx=erfenx(x+1);
            int yy=erfeny(y-1);
            if(xx>yy){printf("maybe\n");continue;}
            int k=findmax(1,xx,yy);
            if(k<d[mp[y]])
            {
                    if(wen(1,mp[x],mp[y])==true)printf("true\n");
                    else printf("maybe\n");
            }
            else printf("false\n");
            continue;
        }
        if(mp[x]==0&&mp[y]==0){printf("maybe\n");continue;}
        if(mp[x]==0)
        {
            int xx=erfenx(x+1),yy=erfeny(y-1);
            if(xx>yy){printf("maybe\n");continue;}
            int k=findmax(1,xx,yy);
            if(k<d[mp[y]])printf("maybe\n");
            else printf("false\n");
            continue;
        }
        if(mp[y]==0)
        {
            int xx=erfenx(x+1),yy=erfeny(y-1);
            if(xx>yy){printf("maybe\n");continue;}
            int k=findmax(1,xx,yy);
            if(k>=d[mp[x]])printf("false\n");
            else printf("maybe\n");
            continue;
        }
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值