• 【ARC072E】Alice in linear land


    题目

    瑟瑟发抖,这竟然只是个蓝题

    题意大概就是初始在(0),要到坐标为(D)的地方去,有(n)条指令,第(i)条为(d_i)。当收到一条指令(x)后,如果向(D)方向走(x)后距离(D)更近,那么就走;否则就停留在原地。

    现在有(Q)次询问,第(i)次询问为(q_i),问能不能仅改变(d_{q_i}),使得其不能到达(D)

    考虑一个暴力,设(g_{i,j})表示当(D=j)时,只使用后(i)次操作能否到达(j)

    考虑如何求出(g_{i,j})

    转移大概长这样

    [g_{i,j}=left{egin{matrix} g_{i+1,j-d_i} & d_ileq j\ g_{i+1,d_i-j} & j<d_i<2j\ g_{i+1,j}&d_igeq 2j end{matrix} ight. ]

    就是当(d_ileq j)的时候,只能到达距离目标(j-d_i)的地方

    (j<d_i<2j),我们会走过(j)点,到达距离目标(d_i-j)的地方,这个时候翻转一下正方向即可

    (d_i>2j)的时候,显然走过去的点距离目标更远,于是直接不走

    我们再处理出一个数组(pos_i)表示第(i)次操作后距离(D)点的距离

    当遇到一个询问(q_i)的时候,如果我们要改变(d_{q_i}),那么可能我们只能改变为(0)(2 imes pos_{i-1})的数,只有这些才是有效移动

    进行有效移动后距离目标点的距离也只可能从(pos_{i-1})(0),所以只需要(g_{q_i+1,0})(g_{q_i+1,pos_{i-1}})里有一个是(0),那么我们就可以走这个距离,之后就不可能走到目标点了

    这样复杂度是(O(nD))的,显然过不了

    考虑一下如何不求(g)数组,而直接高效询问

    发现我们一次询问只关注(g_{q_i+1})的前(pos_{i-1})项有没有一个(0),显然一个靠前的(0)能影响更多的询问

    所以我们如果知道使得(g_{i,j}=0)最小的(j)在哪里,也能快速回答询问

    (dp_i)表示使得(g_{i,j}=0)最小的(j),考虑求出(dp)数组

    根据上面(g)数组的转移,尝试反推(dp)数组的转移

    (d_igeq 2 imes dp_{i+1})时,(dp_{i}=dp_{i+1})。这对应了上面的第三个转移

    (dp_{i+1}=d_i-j),即(dp_{i}=d_i-dp_{i+1})时,需要满足(d_i-dp_{i+1}<d_i<2(d_i-dp_{i+1})),即(d_i>2 imes dp_{i+1})时。这对应了第二个转移。

    (dp_{i+1}=j-d_i),即(dp_i=dp_{i+1}+d_i)时,需要满足(d_ileq dp_{i+1}+d_i),这显然成立。这对应了上面第三个转移。

    根据条件取上面三个转移的最小值即可,回答询问的时候只需要判断一下(dp_{q_i+1})(pos_{q_{i-1}})的大小关系即可

    代码

    #include<bits/stdc++.h>
    #define re register
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    const int maxn=5e5+5;
    int d[maxn],dp[maxn],pos[maxn];
    int n,D,Q;
    inline int ABS(int x) {return x>=0?x:-x;}
    int main() {
    	n=read();D=read();dp[n+1]=1;
    	for(re int i=1;i<=n;i++) d[i]=read();
    	for(re int i=n;i;--i) {
    		if(d[i]>=2*dp[i+1]) {
    			dp[i]=dp[i+1];
    			if(d[i]>2*dp[i+1]) dp[i]=min(dp[i],d[i]-dp[i+1]);
    		}
    		else dp[i]=dp[i+1]+d[i];
    	} 
    	pos[0]=D;
    	for(re int i=1;i<=n;i++) pos[i]=min(ABS(pos[i-1]-d[i]),pos[i-1]);
    	Q=read();int x;
    	while(Q--) x=read(),puts(dp[x+1]<=pos[x-1]?"YES":"NO");	
    	return 0;
    }
    
    
  • 相关阅读:
    查询快递单号-宅急送快递接口
    对路由转发的浅显理解
    对SpringCloud Zuul 的基本使用总结
    对SpringCloud Hystrix的使用个人总结
    对SpringBoot开箱即用使用方法的浅显理解
    对SpringCloud Hystrix服务降级的浅显理解
    金玉良言
    2种运行时织入的动态代理模式原理和调用流程比较
    记录手动启动Oracle数据库的方式
    基于SpringBoot搭建一个带数据库访问的WEB项目(记录所需的依赖,配置,驱动安装等注意事项)
  • 原文地址:https://www.cnblogs.com/asuldb/p/11550904.html
Copyright © 2020-2023  润新知