您和您的朋友正在玩游戲真人快打XI。您正在嘗試通過挑戰塔。該塔中有n個凸台,從1到n。第i個老板的類型是ai。如果第i個首領很容易,則其類型為ai = 0,否則,此首領為堅硬且其類型為ai = 1。
題意:
在一個會話中,您或您的朋友可以殺死一個或兩個老板(您和您的朋友都不能跳過該會話,因此在一個會話中被殺死的老板最少要有一個)。在您的朋友會話之后,您的會話開始,然后再次您的朋友會話開始,您的會話開始,依此類推。第一場是您朋友的一場。
您的朋友需要變得良好,因為他實際上無法殺死艱難的老板。為了殺死他們,他使用了跳過點。一個跳過點可以用來殺死一個堅強的上司。
您的任務是找到您的朋友需要使用的最小跳過點數,以便您和您的朋友按給定順序殺死所有n個頭目。
例如:假設n = 8,a = [1,0,1,1,0,1,1,1]。那么最好的做法是:
您的朋友殺死了兩個首領,對首個老板使用一個跳躍點;
您殺死了第三和第四位老板;
您的朋友殺死了第五任老板;
你殺死了第六和第七個boss;
您的朋友使用一個跳過點殺死了最后一個老板,因此使用兩個跳過點完成了塔。
您必須回答t個獨立的測試用例。
輸入項
輸入的第一行包含一個整數t(1≤t≤2⋅104)—測試用例的數量。然后是t個測試用例。
測試用例的第一行包含一個整數n(1≤n≤2⋅105)-凸台數。測試用例的第二行包含n個整數a1,a2,…,an(0≤ai≤1),其中ai是第i個首部的類型。
保證n的總和不超過2⋅105(∑n≤2⋅105)。
輸出量
對於每個測試用例,請打印答案:朋友需要使用的最小跳過點數,以便您和朋友按給定順序殺死所有n個頭目。
題解:
規律題,思考后可以發現,除了開頭為1的情況,任意一段連續為1的子序列,都能轉化為我先手,朋友后手的情況。依次枚舉算貢獻即可。
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+100; const int inf=1e9; int n; int t; int a[maxn]; int main () { scanf("%d",&t); while (t--) { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",a+i); a[n+1]=0; int ans=0; int tot=0; //貪心 //把盡可能多的1留給我 //對於一段連續是1的長度是k的區間 //如果朋友先手, ans+=k/3+(k%3>0?1:0) //如果我先手,ans+=k/3 int f=0; for (int i=1;i<=n;i++) { if (!a[i]) continue; int j; for (j=i;j<=n;j++) if (a[j]==0) break; int k=j-i; if (i>1) ans+=k/3; else { ans+=k/3+(k%3>0?1:0); f++; } i=j-1; } printf("%d\n",ans); } }