Problem Specification Value
Time Limit 1 Sec
Memory Limit 162 MB
Submit 3535
Solved 919

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,-109<=yi<=109, 1<=ri<=10^9

Source

POJ 2637 WorstWeather Ever

一道极其奇怪的特判题...... 一连拍+交了 N 多遍都没有 AC, 但是和 HZW 的代码相比没有 WA.

有什么可说的呢? 自己看代码吧~



#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <map>

using namespace std;
typedef long long ll;
const int maxn = 131100;

class SegmentTree
{
public:
    // Segment tree optimized for maximum values' lookup and **not** modification.
    // Used for query purposes only.
    int n;
    int lbnd[maxn], rbnd[maxn];
    ll  vmx[maxn];
    void build_tree(int _n, ll* arr)
    {
        n = 1; while (n < _n) n *= 2;
        for (int i = 1; i <= n; i++) {
            lbnd[i + n - 1] = rbnd[i + n - 1] = i;
            vmx[i + n - 1] = arr[i];
        }
        for (int i = n - 1; i >= 1; i--) {
            lbnd[i] = lbnd[2 * i];
            rbnd[i] = rbnd[2 * i + 1];
            vmx[i] = max(vmx[2 * i], vmx[2 * i + 1]);
        }
        return ;
    }
    ll query(int p, int l, int r)
    {
        if (lbnd[p] == l && rbnd[p] == r)
            return vmx[p];
        if (l >= lbnd[2 * p + 1])
            return query(2 * p + 1, l, r);
        else if (r <= rbnd[2 * p])
            return query(2 * p, l, r);
        else
            return max(query(2 * p, l, rbnd[2 * p]),
                    query(2 * p + 1, lbnd[2 * p + 1], r));
    }
    ll query(int l, int r)
    {
        if (l > r) return 0;
        return query(1, l, r);
    }
} st1, st2;

enum determine { True, False, Maybe };

int n, m;
ll  arr1[maxn], arr2[maxn], arr3[maxn];
map<ll, int>    fnd;

ll my_upper_bound(ll x)
{
    if (x < arr1[1])
        return 1;
    int l = 1, r = n;
    while (r > l) {
        int m = (l + r) / 2;
        if (arr1[m] == x)
            return m;
        else if (arr1[m] < x)
            l = m + 1;
        else
            r = m;
    }
    return l;
}

ll my_lower_bound(ll x)
{
    if (x > arr1[n])
        return n;
    int y = my_upper_bound(x);
    if (arr1[y] == x)
        return y;
    else if (arr1[y] > x)
        return y - 1;
    return 1;
}

determine work(int x, int y)
{
    if (x <= y)
        return False;
    // Those should have never happened...
    int x_in, y_in;
    ll  dis_1, dis_2;
    x_in = fnd[x];
    y_in = fnd[y]; // If equals to 0 then not in index
    if (x_in && y_in) {
        // Why would there be such nonsense!
        if (x_in - y_in <= 0)
            return False;
        // There's definitely an answer...
        if (x_in - y_in == 1) {
            if (x - y > 1) // Lacks adjacency
                return arr2[y_in] <= arr2[x_in] ? False : Maybe;
            else if (x - y == 1) // Adjacent means permanence
                return arr2[y_in] <= arr2[x_in] ? False : True;
            else // Doesn't even exists...
                return False;
        } else if (x_in - y_in > 1) {
            if (arr2[y_in] <= arr2[x_in])
                return False;
            dis_1 = st1.query(y_in + 1, x_in - 1);
            dis_2 = st2.query(y_in, x_in - 1);
            if (dis_1 > arr2[x_in])
                return False;
            if (dis_2 > 1)
                return Maybe;
            return True;
        }
    }
    // If one of them has missing data...
    // I'm going to take one of them one at a time, in case I nausea myself
    if (x_in && !y_in) {
        y_in = my_upper_bound(y);
        dis_1 = st1.query(y_in, x_in - 1);
        if (dis_1 < arr2[x_in])
            return Maybe;
        else
            return False;
    } else if (!x_in && y_in) {
        x_in = my_lower_bound(x);
        dis_1 = st1.query(y_in + 1, x_in);
        if (arr2[y_in] > dis_1)
            return Maybe;
        else
            return False;
    }
    // Both of them has missing data means we won't be sure of anything.
    if (!x_in && !y_in)
        return Maybe;
    // That's finally final!
    return False;
}

int main(int argc, char** argv)
{
    scanf("%d", &n);
    fnd.clear();
    for (int i = 1; i <= n; i++) {
        scanf("%lld%lld", &arr1[i], &arr2[i]);
        fnd[arr1[i]] = i; // Index this year in case of finding things...
        if (i >= 2) arr3[i - 1] = arr1[i] - arr1[i - 1];
    }
    st1.build_tree(n, arr2);
    st2.build_tree(n - 1, arr3);
    // Typically responding to queries...
    scanf("%d", &m);
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d%d", &y, &x); // Guranteed that X > Y
        switch (work(x, y)) {
        case True:
            printf("true\n");
            break;
        case False:
            printf("false\n");
            break;
        case Maybe:
            printf("maybe\n");
            break;
        default:
            break;
        }
        continue;
    }
    return 0;
}
上面是错误的
#include<iostream>
#include<cstdio>
using namespace std;
struct data{int ly,ry,mx,know;}tr[200001];
int n,m;
void build(int k,int l,int r)
{
     if(l==r){scanf("%d%d",&tr[k].ly,&tr[k].mx);tr[k].ry=tr[k].ly;tr[k].know=1;return;}
     int mid=(l+r)>>1;
     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
     tr[k].know=(tr[k<<1].know&&tr[k<<1|1].know);
     if(tr[k<<1].ry+1!=tr[k<<1|1].ly)tr[k].know=0;
     tr[k].ly=tr[k<<1].ly;tr[k].ry=tr[k<<1|1].ry;
     tr[k].mx=max(tr[k<<1].mx,tr[k<<1|1].mx);
 }
int get(int k,int x)
{
    if(tr[k].ly==tr[k].ry)
    {
        if(tr[k].ly!=x)return 0;
        else return tr[k].mx;
                        }
    if(x<=tr[k<<1].ry)return get(k<<1,x);
    else if(x>=tr[k<<1|1].ly)return get(k<<1|1,x);
    return 0;
}
int ask(int k,int x,int y,int num)
{
    bool f=0;
    if(x<tr[k].ly){f=1;x=tr[k].ly;}
    if(tr[k].ly==x&&tr[k].ry==y)
    {
                  if(tr[k].mx>=num)return 0;
                  else if(tr[k].know&&!f)return 1;
                  else return 2;
                  }
    if(y<=tr[k<<1].ry)
    {
         return ask(k<<1,x,y,num);
     }
    else if(x>=tr[k<<1|1].ly)
    {
         return ask(k<<1|1,x,y,num);
     }
    else
    {
         int t1=ask(k<<1,x,tr[k<<1].ry,num);
         int t2=ask(k<<1|1,tr[k<<1|1].ly,y,num);
         if(!t1||!t2)return 0;
         else if(tr[k<<1].ry+1!=tr[k<<1|1].ly)return 2;
         else return 1;
     }
}
int getnext(int k,int x)
{
    int l=tr[k].ly,r=tr[k].ry;
    if(l==r)return tr[k].ly;
    if(x<tr[k<<1].ry)return getnext(k<<1,x);
    else return getnext(k<<1|1,x);
}
int getlast(int k,int x)
{
    int l=tr[k].ly,r=tr[k].ry;
    if(l==r)return tr[k].ly;
    if(x>tr[k<<1|1].ly)return getlast(k<<1|1,x);
    else return getlast(k<<1,x);
}
int main()
{
    scanf("%d",&n);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
            int l,r;
            scanf("%d%d",&l,&r);
            if(r<l){printf("false\n");continue;}
            int lnum=get(1,l),rnum=get(1,r);
            if(!lnum&&!rnum)printf("maybe\n");
            else
            {
            int s=getnext(1,l),t=getlast(1,r);
            if(!lnum)
            {
                if(s>t||r==t){printf("maybe\n");continue;}
                int f=ask(1,s,t,rnum);
                if(f==0)printf("false\n");
                else printf("maybe\n");
            }
            else if(!rnum)
            {
                if(s>t||l==s){printf("maybe\n");continue;}
                int f=ask(1,s,t,lnum);
                if(f==0)printf("false\n");
                else printf("maybe\n");
            }
            else
            {
                if(rnum>lnum){printf("false\n");continue;}
                if(s>t){
                     if(l+1==r) printf("true\n");
                     else printf("maybe\n");
                     continue;
                     }
                int f=ask(1,s,t,rnum);
                if(f==0)printf("false\n");
                else if(f==1)
                {
                    if(l+1==s&&r-1==t)printf("true\n");
                    else printf("maybe\n");
                }
                else if(ask(1,s,t,rnum)==2)printf("maybe\n");
                else printf("false\n");
            }
        }
    }
    return 0;
}

from pydatagen import *
n = randrange(100, 500)
m = randrange(3000, 10000)
a1 = randlist(n, range(-10**9, 10**9), distinct=True)
a2 = randlist(n, range(1, 10**9))
a1.sort()
printf('%d\n' % n)
for i in range(0, n):
    printf('%d %d\n' % (a1[i], a2[i]))
printf('%d\n' % m)
for i in range(0, m):
    if possibility(0.6):
        b1 = randlist(2, a1, distinct=True)
        x = b1[0]
        y = b1[1]
        if x < y:
            x, y = y, x
        printf('%d %d\n' % (y, x))
    else:
        if possibility(0.8):
            if possibility(0.5):
                x = choice(a1)
                y = randrange(min(a1), max(a1) + 1)
                if x == y:
                    y = x - 1
                if x < y:
                    x, y = y, x
                printf('%d %d\n' % (y, x))
            else:
                y = choice(a1)
                x = randrange(min(a1), max(a1) + 1)
                if x == y:
                    x = y + 1
                if x < y:
                    x, y = y, x
                printf('%d %d\n' % (y, x))
        else:
            x = randrange(min(a1), max(a1))
            y = randrange(min(a1), max(a1))
            if x == y:
                x = y + 1
            if x < y:
                x, y = y, x
            printf('%d %d\n' % (y, x))
    continue