题目描述
题解
离线离散化, 声明的年份和查找的年份一起建线段树。
线段树维护一下区间最大值,两个点之间是否有没有声明的年份打标记。
判断比较吃屎。
我大的分了两种情况:一个是需要在线段树中查询的,一个是直接判断的。
查询了之后,有好几种情况,分别按照是否出现、权值还有中间是否有相隔的年份来判断。
代码
#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");
}
}
}
总结
手残脑残毁一生。。。