zoukankan      html  css  js  c++  java
  • AT2365-[AGC012E]Camel and Oases【状压dp】

    正题

    题目链接:https://www.luogu.com.cn/problem/AT2365


    题目大意

    一个数轴上有(n)个点,开始你有个水壶容量为(V),你每次有两个操作

    • 走到一个距离与你不超过(V)的点
    • (V=lfloorfrac V2 floor),然后跳到任意一个点。

    对于每个点求从这个点出发能否走到所有点。

    (1leq n,Vleq 2 imes 10^5,-10^9leq x_ileq 10^9)


    解题思路

    显然操作二的次数不会超过(log V),考虑从这里入手。考虑有没有一种方案能够把序列分成若干段,每一段相邻的差不超过给其匹配的一个(lfloorfrac{V}{2^x} floor)(V)的段刚好在起点。

    并且因为(n)很大我们可以考虑改成用数字而不是下标维护它这一维,设(f_{S})表示用集合(S)中的(V)能够从右边走到的最左边的位置,同理(g_S)表示从左边开始走,然后枚举总间段。

    注意到这样的复杂度是(O(nV))的,不过如果一段的左右都已经分出了(log V)个段,那么这个位置也是不合法的(因为)。

    时间复杂度:(O(Vlog V))


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=2e5+10,M=19;
    int n,m,V,w[M],x[N],l[M][N],r[M][N],f[1<<M],g[1<<M],ans[N];
    int main()
    {
    	scanf("%d%d",&n,&V);w[0]=V;
    	while(V){V>>=1;w[++m]=V;}
    	swap(w[0],w[m]);
    	for(int i=1;i<=n;i++)scanf("%d",&x[i]);
    	for(int j=0;j<=m;j++){
    		l[j][1]=1;r[j][n]=n;
    		for(int i=2;i<=n;i++)
    			l[j][i]=(x[i]-x[i-1]<=w[j])?l[j][i-1]:i;
    		for(int i=n-1;i>=1;i--)
    			r[j][i]=(x[i+1]-x[i]<=w[j])?r[j][i+1]:i;
    	}
    	int MS=(1<<m);
    	for(int s=0;s<MS;s++){
    		f[s]=n+1;
    		for(int i=0;i<m;i++){
    			if(!((s>>i)&1))continue;
    			f[s]=min(f[s],l[i][f[s^(1<<i)]-1]);
    			g[s]=max(g[s],r[i][g[s^(1<<i)]+1]);
    		}
    	}
    	int cnt=0;
    	for(int i=1;i<=n;i++){
    		bool flag=0;
    		for(int s=0;s<MS;s++){
    			int t=(MS-1)^s;
    			if(g[s]>=i-1&&f[t]<=r[m][i]+1)
    			{flag=1;break;}
    		}
    		for(int j=i;j<=r[m][i];j++)
    			ans[j]|=flag;
    		cnt++;i=r[m][i];
    		if(cnt>m)break;
    	}
    	cnt=0;
    	for(int i=n;i>=1;i--){
    		bool flag=0;
    		for(int s=0;s<MS;s++){
    			int t=(MS-1)^s;
    			if(f[s]<=i+1&&g[t]>=l[m][i]-1)
    			{flag=1;break;}
    		}
    		for(int j=i;j>=l[m][i];j--)
    			ans[j]|=flag;
    		cnt++;i=l[m][i];
    		if(cnt>m)break;
    	}
    	for(int i=1;i<=n;i++)
    		if(ans[i])puts("Possible");
    		else puts("Impossible");
    	return 0;
    }
    
  • 相关阅读:
    [转载]OpenGL函数参考(中文版)
    [转载]OpenGL 中常用的 GLUT 函数库
    VC6.0 VS2008 openGL环境配置 [和glut库的加入]
    java测试一个类的方法,用junit
    openal配置(更新)
    jsp URL 传参数 服务端接收后乱码的问题
    NeHe OpenGL 第二课 学习总结
    vs2008 添加头文件路径
    困惑之一:c++初始化成员列表
    C++中一些对原理描述相当好得语句
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15497446.html
Copyright © 2011-2022 走看看