[BZOJ1067][SCOI2007]降雨量(线段树)

来源:互联网 发布:java 图形界面案例 编辑:程序博客网 时间:2024/05/22 19:26

题目描述

传送门

题解

离线离散化, 声明的年份和查找的年份一起建线段树。
线段树维护一下区间最大值,两个点之间是否有没有声明的年份打标记。
判断比较吃屎。
我大的分了两种情况:一个是需要在线段树中查询的,一个是直接判断的。
查询了之后,有好几种情况,分别按照是否出现、权值还有中间是否有相隔的年份来判断。

代码

#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>#include<map>using namespace std;const int max_n=1e5+5;const int max_tree=max_n*5;const int INF=1e9;struct hp{    int Maxn,Flag;};struct hq{    int year,val;    bool flag;}a[max_n];struct ho{    int x,y;}ask[max_n];int n,m,N,x,y,lrange,rrange;int year[max_n],val[max_n];bool flag[max_n];int maxn[max_tree],delta[max_tree];map <int,int> hash;map <int,bool> pd;inline int in(){    int x=0,f=1; char ch=getchar();    while (ch<'0'||ch>'9'){        if (ch=='-') f=-1;         ch=getchar();    }    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}inline int cmp(hq a,hq b){    return a.year<b.year||(a.year==b.year&&a.val>b.val)||(a.year==b.year&&a.val==b.val&&a.flag>b.flag);}inline void update(int now){    maxn[now]=max(maxn[now<<1],maxn[now<<1|1]);    delta[now]=delta[now<<1]&&delta[now<<1|1];}inline void build(int now,int l,int r){    int mid=(l+r)>>1;    if (l==r){        maxn[now]=val[l];        delta[now]=flag[l];        return;    }    build(now<<1,l,mid);    build(now<<1|1,mid+1,r);    update(now);}inline hp query(int now,int l,int r,int lrange,int rrange){    hp ans;    int mid=(l+r)>>1;    int MAXN=0;    bool FLAG=true;    if (lrange<=l&&r<=rrange)      return ans=(hp){maxn[now],delta[now]};    if (lrange<=mid){        ans=query(now<<1,l,mid,lrange,rrange);        MAXN=max(MAXN,ans.Maxn);        FLAG=FLAG&&ans.Flag;    }    if (mid+1<=rrange){        ans=query(now<<1|1,mid+1,r,lrange,rrange);        MAXN=max(MAXN,ans.Maxn);        FLAG=FLAG&&ans.Flag;    }    return ans=(hp){MAXN,FLAG}; }int main(){    n=in();    a[0].year=-INF;    for (int i=1;i<=n;++i){        a[i].year=in()+INF; a[i].val=in();        pd[a[i].year]=true;        if (a[i].year==a[i-1].year+1) a[i].flag=true;        else a[i].flag=false;    }    m=in();    for (int i=1;i<=m;++i){        ask[i].y=in()+INF; ask[i].x=in()+INF;        a[++n].year=ask[i].y;        a[n].val=a[n].flag=0;        a[++n].year=ask[i].x;        a[n].val=a[n].flag=0;    }    sort(a+1,a+n+1,cmp);    for (int i=1;i<=n;++i)      if (a[i].year!=a[i-1].year){        hash[a[i].year]=++N;        val[N]=a[i].val;        flag[N]=a[i].flag;      }    build(1,1,N);    for (int i=1;i<=m;++i){        y=ask[i].y; x=ask[i].x;        lrange=hash[y]; rrange=hash[x];        bool pd1=pd[y],pd2=pd[x];        if (lrange>rrange){            printf("false\n");            continue;        }        if (lrange==rrange){            if (pd1) printf("true\n");            else printf("maybe\n");            continue;        }        if (lrange+1==rrange){            if (!pd1&&!pd2) printf("maybe\n");            else if (!pd1||!pd2) printf("maybe\n");            else{                if (val[lrange]<val[rrange]) printf("false\n");                else{                    if (y+1==x) printf("true\n");                    else printf("maybe\n");                }            }            continue;        }        hp ans=query(1,1,N,lrange+1,rrange-1);        if (!pd1&&!pd2){            printf("maybe\n");            continue;        }        if (!pd1){            if (ans.Maxn>=val[rrange]) printf("false\n");            else printf("maybe\n");            continue;        }        if (!pd2){            if (ans.Maxn>=val[lrange]) printf("false\n");            else printf("maybe\n");            continue;        }        if (val[lrange]<val[rrange]) printf("false\n");        else if (ans.Maxn>=val[rrange]) printf("false\n");        else{            if (!(ans.Flag&&flag[rrange])) printf("maybe\n");            else printf("true\n");        }    }}

总结

手残脑残毁一生。。。

0 0
原创粉丝点击