zoukankan      html  css  js  c++  java
  • EOJ 3246 实验室传染病

    线段树,暴力。

    先处理出每个点直接能感染到的最左边的和最右边的。

    之后每次扩展,看向左能到达的那些点中,最左以及最右能到哪些点,更新。

    看向右能到达的那些点中,最左以及最右能到哪些点,更新。

    最左最右能到哪些点,可以用线段树计算区间最小值最大值。

    如果某次无法更新,那么结束。

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    int n;
    struct X
    {
    	int x,y;
    	int ll,rr;
    	int id;
    }s[100010];
    
    int L[100010], R[100010], ans[100010];
    
    bool cmp(X a,X b)
    {
    	return a.x<b.x;
    }
    
    int mn[2][4*100010];
    int mx[2][4*100010];
    
    int B;
    
    void update(int op,int pos,int val,int l,int r,int rt)
    {
    	if(l==r)
    	{
    		mn[op][rt] = mx[op][rt] = val;
    		return ;
    	}
    
    	int mid = ( l + r) / 2;
    	if(pos<=mid) update(op,pos,val,l,mid,2*rt);
    	else update(op,pos,val,mid+1,r,2*rt+1);
    	
    	mn[op][rt] = min(mn[op][2*rt], mn[op][2*rt+1]);
    	mx[op][rt] = max(mx[op][2*rt], mx[op][2*rt+1]);
    }
    
    void MIN(int op,int L,int R,int l,int r,int rt)
    {
    	if(L<=l&&r<=R)
    	{
    		B = min(B,mn[op][rt]);
    		return ;
    	}
    
    	int mid = ( l + r) / 2;
    	if(L<=mid) MIN(op,L,R,l,mid,2*rt);
    	if(R>mid) MIN(op,L,R,mid+1,r,2*rt+1);
    }
    
    void MAX(int op,int L,int R,int l,int r,int rt)
    {
    	if(L<=l&&r<=R)
    	{
    		B = max(B,mx[op][rt]);
    		return ;
    	}
    
    	int mid = ( l + r) / 2;
    	if(L<=mid) MAX(op,L,R,l,mid,2*rt);
    	if(R>mid) MAX(op,L,R,mid+1,r,2*rt+1);
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) 
    	{
    		scanf("%d%d",&s[i].x,&s[i].y);
    		s[i].ll = s[i].x - s[i].y;
    		s[i].rr = s[i].x + s[i].y;
    		s[i].id = i;
    	}
    
    	sort(s+1,s+1+n,cmp);
    	
    	for(int i=1;i<=n;i++) 
    	{
    		int left = 1, right = i, pos;
    		while(left <= right)
    		{
    			int mid = (left + right)/2;
    			if(s[mid].x >= s[i].ll) pos = mid, right = mid-1;
    			else left = mid + 1;
    		}
    
    		L[i] = pos;
    
    		left = i, right = n;
    		while(left<=right)
    		{
    			int mid = (left + right)/2;
    			if(s[mid].x <= s[i].rr) pos = mid, left = mid+1;
    			else right = mid - 1;
    		}
    
    		R[i] = pos;
    	}
    
    	for(int i=1;i<=n;i++)
    	{
    		update(0,i,L[i],1,n,1);
    		update(1,i,R[i],1,n,1);
    	}
    
    	while(1)
    	{
    		bool f = 0;
    
    		for(int i=1;i<=n;i++)
    		{
    			B = n+1;
    			MIN(0,L[i],i,1,n,1);
    			if(B != L[i]) f=1, L[i] = B, update(0,i,L[i],1,n,1);
    		}
    
    		for(int i=n;i>=1;i--)
    		{
    			B = 0;
    			MAX(1,i,R[i],1,n,1);
    			if(B != R[i]) f=1, R[i] = B, update(1,i,R[i],1,n,1);
    		}
    
    		for(int i=1;i<=n;i++)
    		{
    			B = 0;
    			MAX(1,L[i],i,1,n,1);
    			if(B != R[i]) f=1, R[i] = B, update(1,i,R[i],1,n,1);
    		}
    
    		for(int i=n;i>=1;i--)
    		{
    			B = n+1;
    			MIN(0,i,R[i],1,n,1);
    			if(B != L[i]) f=1, L[i] = B, update(0,i,L[i],1,n,1);
    		}
    		
    		if( f == 0 ) break;
    	}
    
    	for(int i=1;i<=n;i++) ans[s[i].id] = R[i] - L[i] + 1;
    
    	for(int i=1;i<=n;i++)
    	{
    		printf("%d",ans[i]);
    		if(i<n) printf(" ");
    		else printf("
    ");
    	}
    
    	return 0;
    }
  • 相关阅读:
    docker 管理应用程序数据和网络管理
    docker安装和基本命令
    Jenkins
    Ansible批量自动化管理工具 roles标准化
    git分布式版本管理系统
    zabbix监控nginx+php-fpm,mysql+主从复制+高可用,tomcat,redis web状态
    zabbix*邮件报警 *用户参数User parameters *定义key值 *Agentd主动模式与被动模式
    修改mvc5的视图模板
    centOS安装Ftp
    重置Mysql自增列的开始序号
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6850316.html
Copyright © 2011-2022 走看看