題意:這個人的運動方式類似於77C - Beavermuncher-0xFF 求最後最多可以走過的點。
做法:假設一個人最後回到j,最多可以走過的點,可以先求出i-0-i,i-n-i,最多可以走過的點數,這個可以用直接貪心,設在把i-n之間的橋都走塌陷的情況下可以做過最多的點
還可以求出0-i(不經過兩點範圍之外的點)最多可以做過的點 sum[i]。
然後dp[j]=sum[j]-sum[i]+left[j]+right[i]=sum[j]+left[j]+left[i]-sum[i],這個可以用單調隊列記錄
這種題目首先要暴力枚舉出發點和終點,然後在判斷走迴路和不走迴路的情況。這裡的運動是可以歸類的,千萬不要被一開始看似無需的情況搞暈啊》。。。
#include<vector>#include<algorithm>#include<cstdio>#include<cstring>#include<queue>#define LL long longconst int LMT=100005;using namespace std;LL lef[LMT],rig[LMT],sum[LMT],bri[LMT];struct comp { bool operator()(const int i, const int j) { return lef[i]-sum[i]<lef[j]-sum[j]; } }; priority_queue<int,vector<int>,comp> que; int main(void) { int n;LL ans=0; scanf("%d",&n); for(int i=1;i<n;i++) { scanf("%I64d",&bri[i]); if(bri[i]>=2)lef[i]+=lef[i-1]; lef[i]+=bri[i]&1?bri[i]-1:bri[i]; sum[i]+=sum[i-1]+(bri[i]&1?bri[i]:bri[i]-1); } for(int i=n-1;i>=0;i--) { rig[i]+=bri[i+1]&1?bri[i+1]-1:bri[i+1]; if(bri[i+1]>=2)rig[i]+=rig[i+1];//靠!! } for(int i=0;i<n;i++) { que.push(i); ans=max(ans,lef[que.top()]-sum[que.top()]+sum[i]+rig[i]); } printf("%I64d\n",ans); return 0; }