• [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;
    }
    
    
  • 相关阅读:
    FFTW3学习笔记2:FFTW(快速傅里叶变换)中文参考
    小程序中用rich-text来实现ul功能 (代码)
    微信小程序中如何实现列表渲染多层嵌套循环
    小程序中实现选择预览图片同时可以实现长按删除图片的代码
    微信小程序实例:获取当前城市位置及再次授权地理位置的代码实现
    微信小程序实例:实现顶部tab切换以及滑动切换时导航栏会随着移动的效果(代码)
    入门微信小程序直播
    微信小程序之登录态
    微信小程序之本地缓存
    微信小程序之页面路由
  • 原文地址:https://www.cnblogs.com/AireenYe/p/cf1642E.html
Copyright © 2020-2023  润新知