zoukankan      html  css  js  c++  java
  • 【ARC072E】Alice in linear land DP

    题目大意

      有一个人要去直线上(lm)远处的地方,他会依次给他的机器发出(n)个指令。第(i)个指令为(d_i)。他的机器收到一个指令(x)后,如果向目的地方向前进(xm)后比当前离目的地更近,就会向前移动(xm),否则什么都不会做。

      现在,给你(q)个询问,第(i)个询问为(a_i),问你能不能改变(d_{a_i}),使得这个人不能到达目的地。你可以决定把(d_{a_i})改成什么数。

      (n,qleq 500000,1leq d_ileq {10}^9)

    题解

      首先我们先算出执行前面(i)个指令后离终点的距离(c_i)

      暴力的做法是用DP算出(g_{i,j}):执行后面(i)~(n)的指令,离终点的距离为(j),执行完后能不能到达终点。

      然后就会发现一旦出现一个(0),后面的(1)就会无意义。(因为可以修改成直接走到(0)这里)

      那么我们只需要维护前面有多少个(1)

      (f_i)表示执行后面(i)~(n)的指令,前面(g_{i,0})~(g_{0,f_i})全部是(1)(g_{i,f_i+1})(0)

      那么如果(d_ileq 2f_{i+1}+1),那么(f_i=f_{i+1}+d_i)。否则(f_i=f_{i+1})

      可以发现,第一种情况(0)~(f_i)之间不会有空洞。

      询问(a_i)时直接判断(c_{a_i-1})是不是比(f_{a_i+1})大。这样直接走到(f_{a_i+1}+1)就可以了。

      时间复杂度:(O(n))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    int n,q;
    ll m;
    ll d[500010];
    ll c[500010];
    ll f[500010];
    void rd(int &s)
    {
    	int c;
    	while((c=getchar())<'0'||c>'9');
    	s=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    		s=s*10+c-'0';
    }
    void rd(ll &s)
    {
    	int c;
    	while((c=getchar())<'0'||c>'9');
    	s=c-'0';
    	while((c=getchar())>='0'&&c<='9')
    		s=s*10+c-'0';
    }
    int abs(int x)
    {
    	return x>0?x:-x;
    }
    void yes()
    {
    	putchar('Y');
    	putchar('E');
    	putchar('S');
    	putchar('
    ');
    }
    void no()
    {
    	putchar('N');
    	putchar('O');
    	putchar('
    ');
    }
    int main()
    {
    #ifdef DEBUG
    	freopen("a.in","r",stdin);
    	freopen("a.out","w",stdout);
    #endif
    	scanf("%d%lld",&n,&m);
    	int i;
    	ll x;
    	c[0]=m;
    	for(i=1;i<=n;i++)
    	{
    		rd(d[i]);
    		c[i]=min(c[i-1],abs(c[i-1]-d[i]));
    	}
    	f[n+1]=0;
    	for(i=n;i>=1;i--)
    	{
    		f[i]=f[i+1];
    		if(d[i]<=2*f[i+1]+1)
    			f[i]=max(f[i],f[i+1]+d[i]);
    	}
    	scanf("%d",&q);
    	for(i=1;i<=q;i++)
    	{
    		rd(x);
    		if(c[x-1]>f[x+1])
    			yes();
    		else
    			no();
    	}
    	return 0;
    }
    
  • 相关阅读:
    Tomcat安装和配置过程
    Java集合框架概述
    Hash表的原理
    Java 浅拷贝和深拷贝的理解和实现方式
    Nginx 配置上传文件大小
    将博客搬至CSDN
    vscode中设置vue代码片段
    底部标签栏获取token失败
    Eacharts K线报错问题
    阿里字体图标库在项目中引用
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8513321.html
Copyright © 2011-2022 走看看