Problem
Solution
考虑用 g [ i ] [ j ] g[i][j] g[i][j]表示当前位置离终点距离为 j j j,执行 [ i , n ] [i,n] [i,n]中的所有命令能否走到终点。
然后你会发现如果要修改的话,按照贪心的思想,最优肯定是无法走到的最小的 j j j作贡献,那么我们其实就只需要保存最小的无法走到的 j j j是多少即可。考虑用 f [ i ] f[i] f[i]表示最大的数使得 g [ i ] [ 0 ] ⋯ g [ i ] [ f [ i ] ] = 1 g[i][0]\cdots g[i][f[i]]=1 g[i][0]⋯g[i][f[i]]=1。那么如果当前走的步数大于等于 ( f [ i + 1 ] + 1 ) ∗ 2 (f[i+1]+1)*2 (f[i+1]+1)∗2,就位置不会发生变化,否则就可以延伸这么多步。
最后询问,如果能使得无法走到的话就要满足 d i s [ x − 1 ] > f [ x + 1 ] dis[x-1]>f[x+1] dis[x−1]>f[x+1]。
时间复杂度 O ( n + q ) O(n+q) O(n+q)
Code
#include <cstdio>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=500010;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,m,d,x,a[maxn],dis[maxn],f[maxn];
inline int abs(int x){return x<0?-x:x;}
int main()
{
read(n);read(dis[0]);
for(rg int i=1;i<=n;i++)
{
read(a[i]);dis[i]=dis[i-1];
getmin(dis[i],abs(dis[i-1]-a[i]));
}
read(m);f[n+1]=0;
for(rg int i=n;i;i--)
{
f[i]=f[i+1];
if(a[i]<=(f[i+1]<<1|1)) f[i]+=a[i];
}
while(m--)
{
read(x);
if(dis[x-1]>f[x+1]) puts("YES");
else puts("NO");
}
return 0;
}