bzoj 1067: [SCOI2007]降雨量 (离散化+线段树)

链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1067

思路: 毒瘤题,写的自闭,改了一晚上,注意要理清题目的逻辑 x小于等于y,x,y之间的数严格小于x,不能等于;

分类讨论懒得写的,很简单的分类讨论。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
const int M = 1e5+10;
const int inf = 0x3f3f3f3f;
int vis[M];
int num[M<<2],sum[M<<2],x1[M],x2[M],yy[M],y2[M],cnt,a[M<<2];
void pushup(int rt){
    sum[rt] = max(sum[rt<<1],sum[rt<<1|1]);
    num[rt] = num[rt<<1] + num[rt<<1|1];
}
 
void update(int p,int c,int l,int r,int rt){
    if(l == r){
        sum[rt] = c;
        num[rt] = 1;
        return ;
    }
    mid;
    if(p <= m) update(p,c,lson);
    else update(p,c,rson);
    pushup(rt);
}
 
int query(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return sum[rt];
    }
    mid;
    int ret = -inf;
    if(L <= m) ret = max(ret,query(L,R,lson));
    if(R > m) ret = max(ret,query(L,R,rson));
    return ret;
}
 
int ask(int L,int R,int l,int r,int rt){
    if(L <= l&&R >= r){
        return num[rt];
    }
    mid;
    int ret = 0;
    if(L <= m) ret += ask(L,R,lson);
    if(R > m) ret += ask(L,R,rson);
    return ret;
}
 
int main()
{
    int n,x,y,m;
    scanf("%d",&n);
    int cnt = 0;
    for(int i = 1;i <= n;i ++){
        scanf("%d%d",&x1[i],&yy[i]);
        a[++cnt] = x1[i];
    }
    scanf("%d",&m);
    for(int i = 1;i <= m;i ++){
        scanf("%d%d",&x2[i],&y2[i]);
        a[++cnt] = x2[i];
        a[++cnt] = y2[i];
    }
    sort(a+1,a+1+cnt);
    int nn = unique(a+1,a+1+cnt)-(a+1);
    for(int i = 1;i <= n;i ++){
        x = lower_bound(a+1,a+nn+1,x1[i]) - a;
        vis[x] = yy[i];
        update(x,yy[i],1,nn,1);
    }
    for(int i = 1;i <= m;i ++){
        x = lower_bound(a+1,a+nn+1,x2[i]) - a;
        y = lower_bound(a+1,a+nn+1,y2[i]) - a;
        if(x > y){
            printf("false\n");
            continue;
        }
        if(!vis[x]&&!vis[y]) printf("maybe\n");
        else if(vis[x]&&vis[y]){
            int cnt = query(x+1,y-1,1,nn,1);
            int flag = ask(x,y,1,nn,1);
            if(cnt<vis[y]&&vis[y]<=vis[x]){
                if(flag == y2[i]-x2[i]+1) printf("true\n");
                else printf("maybe\n");
            }
            else printf("false\n");
        }
        else if(!vis[x]&&vis[y]){
            int cnt = query(x,y-1,1,nn,1);
            if(cnt >= vis[y]) printf("false\n");
            else printf("maybe\n");
        }
        else{
            int cnt = query(x+1,y,1,nn,1);
            if(cnt >= vis[x]) printf("false\n");
            else printf("maybe\n");
        }
    }
    return 0;
}

 

posted @ 2019-03-26 21:02  冥想选手  阅读(112)  评论(0编辑  收藏  举报