这题神啊。状压dp你敢信?思维难度爆表还有一堆细节要注意???orz Visjiao
原题链接:http://agc012.contest.atcoder.jp/tasks/agc012_e
大神题解:http://blog.csdn.net/vicjiao/article/details/78405844
tips:dp数组大小要开到2*V,因为最多可以飞 log2v+1 次,所以是 2log2v+1−1 ,而不是v。坑啊orz
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 200010
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
int n,v,tot=-1,bin[22],R[22][N],num[22],f1[N<<3],f2[N<<3],a[N];//R[i][k],第i层的第k条线段的右端点
//num[i],第i层的线段条数 f1[s],选择s状态的层数,左边从1开始最远能覆盖到哪里
int main(){
// freopen("a.in","r",stdin);
n=read();v=read();bin[0]=1;
for(int i=1;i<=20;++i) bin[i]=bin[i-1]<<1;
for(int i=1;i<=n;++i) a[i]=read();int x=v*2;
while(x){
x/=2;tot++;
for(int i=1;i<=n-1;++i){
if(a[i+1]-a[i]<=x) continue;
R[tot][++num[tot]]=i;
}R[tot][++num[tot]]=n;
}if(num[0]>tot+1){
for(int i=1;i<=n;++i) puts("Impossible");return 0;
}
for(int s=0;s<=bin[tot]-1;++s) f2[s]=n+1;
for(int s=0;s<=bin[tot]-1;++s)
for(int i=1;i<=tot;++i){
if(s&bin[i-1]) continue;
f1[s|bin[i-1]]=max(f1[s|bin[i-1]],*upper_bound(R[i]+1,R[i]+num[i]+1,f1[s]));
f2[s|bin[i-1]]=min(f2[s|bin[i-1]],R[i][lower_bound(R[i]+1,R[i]+num[i]+1,f2[s]-1)-R[i]-1]+1);
}
for(int i=1;i<=num[0];++i){
bool flag=0;
for(int s=0;s<=bin[tot]-1;++s)
if(f1[s]>=R[0][i-1]&&f2[bin[tot]-1-s]<=R[0][i]+1){flag=1;break;}
for(int j=R[0][i-1]+1;j<=R[0][i];++j) puts(flag?"Possible":"Impossible");
}return 0;
}