[cf1642E]Anonymity Is Important
Description
q次在线操作,实时告诉区间[l,r]有/没有病人,询问病人x是否一定患病/无病。
Solution
用时间戳在线转离线。
一个病人无病当且仅当他属于某个无病区间。
一个病人一定有病当且仅当他在某个除了他都没病的有病区间内。
否则不确定是否有病。
可以发现,有病区间互不干扰。
只需先处理出无病的病人,记录他们最早被确定无病的时间。
再对于每个有病区间求是否只有一个病人可能有病,记录病人最早被确定有病的时间。
对于每个询问,只要晚于最早被确定有/无病的时间,就可以确定,否则为不确定。
处理方法一
用线段树记录每个区间是否全为有病/除了一个外其余全都有病,记录每个区间的时间戳最大值。
处理方法二
用set记录可能有病的病人。
依次删去无病区间的点,记录他们最早被确定无病的时间。
再对每个有病区间求区间内是否存在第二个可能有病的人,更新病人最早被确定有病的时间。
#include<bits/stdc++.h>
using namespace std;
const int N=200005,M=800005;
struct patient{
int ty;//1:YES,sick; 0:N/A:0; -1,NO.not sick
int t;
}ans[N];
struct SegmentTree{
int t;
}lt[M];
struct update{
int l,r,t;
}ud1[N],ud2[N];
struct query{
int x,t;
}q[N];
int n,m,m1,m2,t;
set<int> s;
void build(int u,int l,int r){
if(l==r){
lt[u].t=ans[l].t;
return;
}
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
lt[u].t=max(lt[u<<1].t,lt[u<<1|1].t);
}
int ask(int u,int lef,int rig,int l,int r){
if(l<=lef&&rig<=r)
return lt[u].t;
int ret=0,mid=(lef+rig)>>1;
if(l<=mid) ret=max(ret,ask(u<<1,lef,mid,l,r));
if(r>mid) ret=max(ret,ask(u<<1|1,mid+1,rig,l,r));
return ret;
}
int main(){
scanf("%d%d",&n,&t);
for(int i=1,ty,l,r,x;i<=t;++i){
scanf("%d",&ty);
if(ty){
scanf("%d",&x);
q[++m]=(query){x,i};
}
else{
scanf("%d%d%d",&l,&r,&x);
if(x) ud1[++m1]=(update){l,r,i};
else ud2[++m2]=(update){l,r,i};
}
}
for(int i=1;i<=n;++i)
s.insert(i);
for(int i=1;i<=m2;++i){
set<int>::iterator u=s.lower_bound(ud2[i].l);
while(u!=s.end()&&(*u)<=ud2[i].r){
ans[*u]=(patient){-1,ud2[i].t};
s.erase(u++);
}
}
build(1,1,n);
for(int i=1;i<=m1;++i){
if(ud1[i].l==ud1[i].r){
if(!ans[ud1[i].l].ty||ud1[i].t<ans[ud1[i].l].t)
ans[ud1[i].l]=(patient){1,ud1[i].t};
continue;
}
set<int>::iterator u1=s.lower_bound(ud1[i].l);
if(u1==s.end()) continue;
set<int>::iterator u2=u1;++u2;
if((*u1)<=ud1[i].r&&(u2==s.end()||(*u2)>ud1[i].r)){
int t=max(ud1[i].t,ask(1,1,n,ud1[i].l,ud1[i].r));
if(!ans[*u1].ty||t<ans[*u1].t) ans[*u1]=(patient){1,t};
}
}
for(int i=1;i<=m;++i){
if(!ans[q[i].x].ty||ans[q[i].x].t>q[i].t)
printf("N/A\n");
else if(ans[q[i].x].ty>0) printf("YES\n");
else printf("NO\n");
}
return 0;
}