生活随笔
收集整理的這篇文章主要介紹了
AGC 012 E Camel and Oases - 状压dp
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目大意:數軸上有n個不同的點,你有一個能量,初始是v。可以進行兩種操作,走到左邊/右邊一個點,如果當前能量大于等于距離。或者隨意跳到一個點,但是要求能量不是0并且能量要減半(向下取整)。對每個點求從這個點出發能否到達所有點。一個點可以經過多次。n,v≤2×105,∣xi∣≤109n,v\le2\times10^5,|x_i|\le10^9n,v≤2×105,∣xi?∣≤109
題解:
首先v只會減半logv次就拜拜了。
考慮一開始在一個點,你能到達一個區間。
然后你需要把哪些減半后的v用于走左邊,剩下的走右邊。
直接枚舉子集就死了,轉為求如果想要從1走到i,最小能從多小的j出發走到n。處理LF[S]表示S這個集合的v最遠能從1走到那里,RF同理,然后就做完了。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std
;inline int inn() { int x
;scanf("%d",&x
);return x
; }const int N
=270000,LOG
=20;int x
[N
],v
[N
],L
[LOG
][N
],R
[LOG
][N
],val
[N
],Lf
[N
],Rf
[N
];
int main()
{int n
=inn(),k
=0;v
[0]=inn();rep(i
,1,n
) x
[i
]=inn();while(v
[k
]) v
[k
+1]=v
[k
]>>1,k
++;int all
=(1<<k
)-1;rep(i
,0,k
){L
[i
][1]=1;for(int j
=1+1;j
<=n
;j
++) if(x
[j
]-x
[j
-1]<=v
[i
]) L
[i
][j
]=L
[i
][j
-1];else L
[i
][j
]=j
;R
[i
][n
]=n
;for(int j
=n
-1;j
>=0;j
--) if(x
[j
+1]-x
[j
]<=v
[i
]) R
[i
][j
]=R
[i
][j
+1];else R
[i
][j
]=j
;}rep(i
,1,all
) Lf
[i
]=1,Rf
[i
]=n
;Lf
[0]=0,Rf
[0]=n
+1;rep(i
,0,all
) rep(j
,1,k
) if(!((i
>>(j
-1))&1)) Lf
[i
|(1<<(j
-1))]=max(Lf
[i
|(1<<(j
-1))],R
[j
][Lf
[i
]+1]),Rf
[i
|(1<<(j
-1))]=min(Rf
[i
|(1<<(j
-1))],L
[j
][Rf
[i
]-1]);rep(i
,0,n
+1) val
[i
]=n
+n
;rep(i
,0,all
) val
[Lf
[i
]]=min(val
[Lf
[i
]],Rf
[all
^i
]);for(int i
=n
;i
>=0;i
--) val
[i
]=min(val
[i
],val
[i
+1]);rep(i
,1,n
) printf(val
[L
[0][i
]-1]<=R
[0][i
]+1?"Possible\n":"Impossible\n");return 0;
}
總結
以上是生活随笔為你收集整理的AGC 012 E Camel and Oases - 状压dp的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。