zoukankan      html  css  js  c++  java
  • 【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();
    }
    
  • 相关阅读:
    AtCoder Beginner Contest 167
    AtCoder Beginner Contest 166
    AtCoder Beginner Contest 165
    AtCoder Beginner Contest 164
    AtCoder Beginner Contest 163
    AtCoder Beginner Contest 162
    AtCoder Beginner Contest 161
    AtCoder Beginner Contest 160
    AtCoder Beginner Contest 159
    自定义Mybatis自动生成代码规则
  • 原文地址:https://www.cnblogs.com/yoyoball/p/9805756.html
Copyright © 2011-2022 走看看