[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;
}