• 【agc012E】Camel and Oases


    Portal --> agc012

    Description

      有一排点,两点间有一定距离,初始的时候有一个行走值(v),如果说两点间距离不超过(v),那么可以在这两点间自由行走,如果当前(v>0)那么可以选择突然出现在任意一点,但是这样做之后(v)会减半(下取整),问每个位置出发能否到达所有的位置至少一次

      

    Solution

      额其实感觉关键还是模型的转化

    ​  其实我们可以比较形象地将每个(v)(就是不停除以(2)直到(0),中途得到的那堆(v)),看成“一层”,具体举个例子的话就是:当(v=4)的时候,第一层为(v=4),第二层为(v=2),第三层为(v=1),第四层为(v=0),这样

    ​  然后每次突然出现其实就相当于往上走了一层,而每层中,有一些区间是可以在区间内随便走的,我们将这些区间看成若干条线段,那么现在的问题就变成了,每层选一条线段,问是否能够覆盖整个区间

    ​  想不到吧然后因为层数上限是(19)所以。。这是一道状压dp的题目==

    ​  

    ​  所以首先,我们先将每一层中的线段处理出来,将第(i)层的线段存在(seg[i])数组里面,只用存右端点即可,左端点可以由前一条线段的右端点(+1)得到

    ​  考虑一下大概要用什么样的方式统计答案,我们可以考虑枚举第一层的每条线段((l_i,r_i)),如果说存在一种方案使得从(1)开始覆盖到一个(>=l_i-1)的位置,从(n)开始覆盖到一个(<=r_i+1)的位置,那么这段线段中的每一个点都是(Possible)的,否则就是(Impossible)

    ​  那么所以,我们考虑维护两个数组(tol)(tor),其中(tor[i])表示线段选择状态(如果这层选了线段那么对应的二进制位为(1)否则为(0))为(i)的情况下,从(1)开始往右最远能覆盖到的位置,(tol[i])表示从(n)开始往左最远能覆盖到的位置,注意,因为最后统计答案的时候,第一层的线段是要枚举的,所以我们在计算(tor)(tol)的枚举状态的时候,不能包含第一层

    ​  接下来定义两个过程:(expandReft(which,x))表示在第(which)层的线段中,严格大于(x)的第一个右端点,(expandLight(which,x))表示在第(which)层的线段中,严格小于(x)的最靠近(n)的右端点

    ​  那么我们可以得到转移式子:

    [egin{aligned} tor[st|St(i)]&=max(tor[st|St(i)],expandRight(i,tor[st]))\ tol[st|St(i)]&=min(tol[st|St(i)],expandLeft(i,tol[st]-1))\ end{aligned} ]

      至于为什么要用(tol[st]-1)的话。。是因为如果直接找(tol[st])的话,我们可能找到(tol[st]),这就说明有一段以(tol[st]-1)为右端点的区间以及一段以(tol[st])为左端点的区间,然而这个时候我们应该找前者而不是后者会出些小问题==(不过也可能只是实现方式的问题。。具体都是看二分查找要怎么写吧都是一些实现上的细节问题qwq)

      那么最后一个小问题就是,如果说第一层有很多条线段的话那就很凉凉,然而实际上,我们发现如果说第一层的线段条数(>logv+1)的话。。就根本不可能覆盖完了(层数不够),所以我们可以在计算之前先判一下这种全部都是(Impossible)的情况

      那所以我们的总复杂度就是(O(nlogv+vlognlogv))

      

      代码大概长这个样子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int N=2*(1e5)+10,ST=1<<20,TOP=20,inf=2e9;
    int seg[TOP+1][N],d[N],tor[ST],tol[ST],a[N];
    int n,m,v,lg,all;
    bool in(int st,int x){return st>>x-1&1;}
    int St(int x){return 1<<x-1;}
    void get_seg(){
    	for (int i=1;i<=lg;++i){
    		seg[i][0]=0;
    		for (int j=1;j<=n;++j){
    			if (j==1||d[j-1]>v>>i-1) ++seg[i][0];
    			seg[i][seg[i][0]]=j;
    		}
    	}
    }
    bool firstcheck(){
    	if (seg[1][0]<=lg) return true;
    	for (int i=1;i<=n;++i) printf("Impossible
    ");
    	return false;
    }
    int expand_right(int which,int x){
    	int l=1,r=seg[which][0],mid,ret=r;
    	while (l<=r){
    		mid=l+r>>1;
    		if (seg[which][mid]>x) ret=mid,r=mid-1;
    		else l=mid+1;
    	}
    	return seg[which][ret];
    }
    int expand_left(int which,int x){
    	int l=1,r=seg[which][0],mid,ret=l;
    	while (l<=r){
    		mid=l+r>>1;
    		if (seg[which][mid]<x) ret=mid,l=mid+1;
    		else r=mid-1;
    	}
    	return seg[which][ret]+1;
    }
    void dp(){
    	all=1<<lg;
    	for (int st=0;st<all;++st) tor[st]=0,tol[st]=n+1;
    	for (int st=0;st<all;st+=2){
    		for (int i=2;i<=lg;++i){
    			if (in(st,i)) continue;
    			tor[st|St(i)]=max(tor[st|St(i)],expand_right(i,tor[st]));
    			tol[st|St(i)]=min(tol[st|St(i)],expand_left(i,tol[st]-1));
    		}
    	}
    }
    void get_ans(){
    	int L,R;
    	bool ok;
    	for (int i=1;i<=seg[1][0];++i){
    		L=i==1?1:seg[1][i-1]+1; R=seg[1][i];
    		ok=false;
    		for (int st=0;st<all&&!ok;st+=2)
    			if (L-1<=tor[st]&&tol[(all-1)-st-1]<=R+1) ok=true;
    		for (int j=L;j<=R;++j) printf(ok?"Possible
    ":"Impossible
    ");
    	}
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("a.in","r",stdin);
    #endif
    	scanf("%d%d",&n,&v);
    	for (int i=1;i<=n;++i) scanf("%d",a+i);
    	d[n]=inf;
    	for (int i=1;i<n;++i) d[i]=a[i+1]-a[i];
    	lg=0;
    	while ((v>>lg)>0) ++lg;
    	++lg;
    	get_seg();
    	if (!firstcheck()) return 0;
    	dp();
    	get_ans();
    }
    
  • 相关阅读:
    kubernetes实战(十六):k8s高可用集群平滑升级 v1.11.x 到v1.12.x
    kubernetes实战(十四):k8s持久化部署gitlab集成openLDAP登录
    kubernetes实战(十三):k8s使用helm持久化部署harbor集成openLDAP登录
    kubernetes实战(十二):k8s使用helm持久化部署redmine集成openLDAP
    kubernetes实战(十一):k8s使用openLDAP统一认证
    Django数据库连接Mysql配置
    HmailServer 无法发信 端口25连接失败 ConnectFail not possible to connect 请看这里
    C++ Opencv安装教程 超详细图解 Vs2015/2017/2019(C++)绑定 VisualStduio
    Python Ftp Ftplib dir()方法 返回值问题
    Collections 初识
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9805756.html
Copyright © 2020-2023  润新知