BZOJ1067: [SCOI2007]降雨量 (RMQ或者线段树)

1067: [SCOI2007]降雨量
Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 4026  Solved: 1067
[Submit][Status][Discuss]
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
这道题真的好坑好坑,而且这道题要看清题意,这里就算是语文题吧,做了好久才做出来。
具体做法有线段树维护区间最大值,或者RMQ-ST预处理,然后分类讨论
这里分好多种情况:
我们这里定 从X年到Y年:
1. X>Y的情况应该可以排除不用考虑
2. X为最大的一年
3. Y为最小的一年,2,3这两点也可以不判断,不过判断了没事
4. 接下来就是重点了:
5. true的情况有:
6. X,Y都已知,且X-1到Y-1年的降雨量要小于Y,且Y年的降雨量不超过X年,并且X年到Y年都要连续的.
7. maybe的情况有:
8. X,Y都未知
9. X,Y这两年中其中有一年未知,X未知,X到Y-1年中任何一年的降雨量都小于Y年。Y未知,X+1到Y年中的任何一年的降雨量都小于X年。
10. X,Y都已知,且X-1到Y-1年的降雨量要小于Y,Y年的降雨量不超过X年,且X+1到Y-1年中至少有一年是未知的。
11. 其他情况就是false了。

RMQ-ST做法:

/**************************************************************
    Problem: 1067
    User: _ostreamBaba
    Language: C++
    Result: Accepted
    Time:172 ms
    Memory:5012 kb
****************************************************************/

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)
#define MOD 1000000007

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 60;
using namespace std;
//#define TIME

inline int read(){
    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;
}

int dpmax[17][50010];
int year[50010];
int rain[50010];
int N, M;

void rmq(int limits){ //预处理
    for(int i = 1; i < limits; ++i){
        for(int j = 1; j <= N; ++j){
            if(j+(1<<i)-1 <= N){
                dpmax[i][j] = max(dpmax[i-1][j], dpmax[i-1][j+(1<<i>>1)]);
            }
        }
    }
}
inline int query(int l, int r){//区间求最值
    if(l > r){  //这种情况是x,y年都已知,且x+1==y
        return -INF;
    }
    else{
        int k = floor(log2(r-l+1));
        return max(dpmax[k][l], dpmax[k][r-(1<<k)+1]);
    }
}

inline int getpos(int p)//获得位置
{
    int pos = lower_bound(year+1, year+N+1, p)-year;
    return pos;
}

int main()
{
   // fin;
   // fout;
    N = read();
    mes(dpmax, 0);
    for(int i = 1; i <= N; ++i){
        year[i] = read();
        rain[i] = read();
        dpmax[0][i] = rain[i];
    }
    rmq(log2(N)+1); 
    M = read();
    while(M--){
        int x, y, l, r, max_rain;
        x = read();
        y = read();
        l = getpos(x);
        r = getpos(y);
     //   cout << query(l, r) << endl;
        bool _l = (l<=N&&year[l]==x);  // find or no_find
        bool _r = (r<=N&&year[r]==y);  // find or no_find
        if(_r == false){  //找不到的话会越界,控制在N内
            --r;
        }
        if(_r && r == 1){
            printf("maybe\n");
            continue;
        }
        else if(_l && l == N){
            printf("maybe\n");
            continue;
        }
        if(!_l && !_r){
            printf("maybe\n");
        }
        else if(!_l && _r){
            max_rain = query(l, r-1);
            if(max_rain < rain[r]){
                printf("maybe\n");
            }
            else{
                printf("false\n");
            }
        }
        else if(_l && !_r){
            max_rain = query(l+1, r);
            if(max_rain < rain[l]){
                printf("maybe\n");
            }
            else{
                printf("false\n");
            }
        }
        else{
            max_rain = query(l+1, r-1);
            if(max_rain < rain[r] && rain[r] <= rain[l]){
                if(y-x == r-l){
                    printf("true\n");
                }
                else{
                    printf("maybe\n");
                }
            }
            else{
                printf("false\n");
            }
        }
    }
}

线段树版本:

/**************************************************************
    Problem: 1067
    User: _ostreamBaba
    Language: C++
    Result: Accepted
    Time:168 ms
    Memory:2464 kb
****************************************************************/

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<ctime>
#include<string>
#include<stack>
#include<deque>
#include<queue>
#include<list>
#include<set>
#include<map>
#include<cstdio>
#include<limits.h>
#define fir first
#define sec second
#define fin freopen("/home/ostreambaba/文档/input.txt", "r", stdin)
#define fout freopen("/home/ostreambaba/文档/output.txt", "w", stdout)
#define mes(x, m) memset(x, m, sizeof(x))
#define pii pair<int, int>
#define Pll pair<ll, ll>
#define INF 1e9+7
#define Pi 4.0*atan(1.0)
#define MOD 1000000007

#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs rt<<1|1

typedef long long ll;
typedef unsigned long long ull;
const double eps = 1e-12;
const int maxn = 50010;
using namespace std;
//#define TIME

inline int read(){
    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;
}

int year[maxn];
int rain[maxn];
int N, M;
int sum[maxn<<2];

void PushUp(int rt)
{
    sum[rt] = max(sum[rt<<1], sum[rt<<1|1]);
}

inline void buildTree(int l, int r, int rt)
{
    if(l == r){
        sum[rt] = rain[l];
        return;
    }
    int m = (l + r) >> 1;
    buildTree(lson);
    buildTree(rson);
    PushUp(rt);
}

inline int query(int L, int R, int l, int r, int rt)
{
    if(L > R){
        return -INF;
    }
    if(L <= l && r <= R){
        return sum[rt];
    }
    int ret = 0;
    int m = (l + r) >> 1;
    if(L <= m){
        ret = max(ret, query(L, R, lson));
    }
    if(R > m){
        ret = max(ret, query(L, R, rson));
    }
    return ret;
}


inline int getpos(int p)
{
    int pos = lower_bound(year+1, year+N+1, p)-year;
    return pos;
}

int main()
{
  //  fin;
   // fout;
    mes(sum, 0);
    N = read();
    for(int i = 1; i <= N; ++i){
        year[i] = read();
        rain[i] = read();
    }
    buildTree(1, N, 1);
    M = read();
    while(M--){
        int x, y, l, r, max_rain;
        x = read();
        y = read();
        l = getpos(x);
        r = getpos(y);
     //   cout << query(l, r, 1, N, 1) << endl;
        bool _l = (l<=N&&year[l]==x);  // find or no_find
        bool _r = (r<=N&&year[r]==y);  // find or no_find
        if(_r == false){
            --r;
        }
        if(_r && r == 1){
            printf("maybe\n");
            continue;
        }
        else if(_l && l == N){
            printf("maybe\n");
            continue;
        }
        if(!_l && !_r){
            printf("maybe\n");
        }
        else if(!_l && _r){
            max_rain = query(l, r-1, 1, N, 1);
            if(max_rain < rain[r]){
                printf("maybe\n");
            }
            else{
                printf("false\n");
            }
        }
        else if(_l && !_r){
            max_rain = query(l+1, r, 1, N, 1);
            if(max_rain < rain[l]){
                printf("maybe\n");
            }
            else{
                printf("false\n");
            }
        }
        else{
            max_rain = query(l+1, r-1, 1, N, 1);
            if(max_rain < rain[r] && rain[r] <= rain[l]){
                if(y-x == r-l){
                    printf("true\n");
                }
                else{
                    printf("maybe\n");
                }
            }
            else{
                printf("false\n");
            }
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值