T1 Lonely Photo
題目
Farmer John has recently acquired N new cows (3≤N≤5×105), each of whose breed is either Guernsey or Holstein.
The cows are currently standing in a line, and Farmer John wants take a photo of every sequence of three or more consecutive cows. However, he doesn't want to take a photo in which there is exactly one cow whose breed is Guernsey or exactly one cow whose breed is Holstein --- he reckons this singular cow would feel isolated and self-conscious. After taking a photo of every sequence of three or more cows, he throws out all of these so-called "lonely" photos, in which there is exactly one Guernsey or exactly one Holstein.
Given the lineup of cows, please help Farmer John determine how many lonely photos he will throw out. Two photos are different if they start or end at different cows in the lineup.
Farmer John 最近購入了 N 頭新的奶牛(3≤N≤5×105),每頭奶牛的品種是更賽牛(Guernsey)或荷斯坦牛(Holstein)之一。
奶牛目前排成一排,Farmer John 想要為每個連續不少於三頭奶牛的序列拍攝一張照片。 然而,他不想拍攝這樣的照片,其中只有一頭牛的品種是更賽牛,或者只有一頭牛的品種是荷斯坦牛——他認為這頭奇特的牛會感到孤立和不自然。 在為每個連續不少於三頭奶牛的序列拍攝了一張照片后,他把所有「孤獨的」照片,即其中只有一頭更賽牛或荷斯坦奶牛的照片,都扔掉了。
給定奶牛的排列方式,請幫助 Farmer John 求出他會扔掉多少張孤獨的照片。如果兩張照片以不同的奶牛開始或結束,則認為它們是不同的。
思路
我們可以考慮每一頭奶牛作為孤獨的奶牛對照片數量的貢獻。
於是我們可以預處理每只奶牛向左和向右與自己不同種類奶牛的連續長度,最后統計即可。
總結
對於此類題目,我們可以對每只奶牛分別考慮對答案的貢獻,通過預處理來求出答案。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 500010
int n, m, i, j, k;
int l[N], r[N], ans;
char a[N];
signed main()
{
scanf("%d%s", &n, a+1);
for(i=1, k=0; i<=n; ++i)
if(a[i]==a[i-1]) l[i]=0, ++k;
else l[i]=k, k=1;
for(i=n, k=0; i>=1; --i)
{
if(a[i]==a[i+1]) r[i]=0, ++k;
else r[i]=k, k=1;
}
for(i=1; i<=n; ++i)
{
if(l[i]&&r[i]) ans+=l[i]*r[i];
if(l[i]>=2) ans+=l[i]-1;
if(r[i]>=2) ans+=r[i]-1;
}
printf("%lld", ans);
return 0;
}
T2 Air Cownditioning
題目
Farmer John's cows N
are very particular about the room temperature in their barn. Some cows like the temperature to be on the cooler side, while others prefer more warmth.
Farmer John's barn contains a sequence of N
stalls, numbered 1…N, each containing a single cow. The i-th cow prefers the temperature of her stall to be pi, and right now the temperature in her stall is ti. In order to make sure every cow is comfortable, Farmer John installs a new air conditioning system that is controlled in a somewhat interesting way. He can send commands to the system telling it to either raise or lower the temperature in a consecutive series of stalls by 1 unit --- for example "raise the temperature in stalls 5…8
by 1 unit". The series of stalls could be as short as just a single stall.
Please help Farmer John determine the minimum number of commands he needs to send his new air conditioning system so that every cow's stall is at the ideal temperature for its resident cow.
Farmer John 的 N 頭奶牛對他們牛棚的室溫非常挑剔。有些奶牛喜歡溫度低一些,而有些奶牛則喜歡溫度高一些。
Farmer John 的牛棚包含一排 N
個牛欄,編號為 1…N,每個牛欄里有一頭牛。 第 i 頭奶牛希望她的牛欄中的溫度是 pi,而現在她的牛欄中的溫度是 ti。為了確保每頭奶牛都感到舒適,Farmer John 安裝了一個新的空調系統。該系統進行控制的方式非常有趣,他可以向系統發送命令,告訴它將一組連續的牛欄內的溫度升高或降低 1 個單位——例如「將牛欄 5…8
的溫度升高 1 個單位」。一組連續的牛欄最短可以僅包含一個牛欄。
請幫助 Farmer John 求出他需要向新的空調系統發送的命令的最小數量,使得每頭奶牛的牛欄都處於其中的奶牛的理想溫度。
思路
我們對於需要加的和需要減的分段考慮。
假設有一段是全部要加的。
我們只需要看一下每一個要比前一個多加多少,因為前一個能加的這個也能加,只需要考慮這一個不能加的即可。
要減的同理。
總結
對於此類題目,我們可以大膽猜測可以分情況討論。同時在考慮變多少的時候,我們可以嘗試和相鄰的進行比較,看看新加的貢獻。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 1000010
int n, m, i, j, k, ans;
int x[N], a[N], y[N];
signed main()
{
scanf("%lld", &n);
for(i=1; i<=n; ++i) scanf("%lld", &x[i]);
for(i=1; i<=n; ++i) scanf("%lld", &y[i]);
for(i=1; i<=n; ++i) a[i]=max((long long)0, x[i]-y[i]);
for(i=1, k=0; i<=n; ++i)
ans+=max((long long)0, a[i]-k), k=a[i];
for(i=1; i<=n; ++i) a[i]=max((long long)0, y[i]-x[i]);
for(i=1, k=0; i<=n; ++i)
ans+=max((long long)0, a[i]-k), k=a[i];
printf("%lld", ans);
return 0;
}
T3 Walking Home
題目
Bessie the cow is trying to walk from her favorite pasture back to her barn.
The pasture and farm are on an N×N
grid (2≤N≤50
), with her pasture in the top-left corner and the barn in the bottom-right corner. Bessie wants to get home as soon as possible, so she will only walk down and to the right. There are haybales in some locations that Bessie cannot walk through; she must walk around them.
Bessie is feeling a little tired today, so she wants to change the direction she walks at most K
times (1≤K≤3
) .
How many distinct paths can Bessie walk from her favorite pasture to the barn? Two paths are distinct if Bessie walks in a square in one path but not in the other
奶牛 Bessie 正准備從她最喜愛的草地回到她的牛棚。
農場位於一個 N×N
的方陣上(2≤N≤50
),其中她的草地在左上角,牛棚在右下角。Bessie 想要盡快回家,所以她只會向下或向右走。有些地方有草堆(haybale),Bessie 無法穿過;她必須繞過它們。
Bessie 今天感到有些疲倦,所以她希望改變她的行走方向至多 K
次(1≤K≤3
)。
Bessie 有多少條不同的從她最愛的草地回到牛棚的路線?如果一條路線中 Bessie 經過了某個方格而另一條路線中沒有,則認為這兩條路線不同。
思路
設 \(dp(x, y, k, 0/1)\) 代表此時在格子 \((x,y)\),已轉彎 \(k\) 次,現在朝着方向下/右(\(0/1\))的方案數。
然后就可以從左邊和上邊轉移過來,轉移的時候需要考慮是否轉彎。
總結
對於棋盤上年統計方案的題目,如果棋盤不是很大,可以考慮dp,把限制條件寫入轉態即可。
Code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n, m, i, j, k, t, kx, p;
int dp[55][55][5][2], ans;
char s[55][55];
signed main()
{
scanf("%lld", &t);
while(t--)
{
memset(dp, 0, sizeof(dp)); ans=0;
scanf("%lld%lld", &n, &k);
for(i=1; i<=n; ++i) scanf("%s", s[i]+1);
if(s[1][1]=='H'){ printf("0\n"); continue; }
dp[1][1][0][0]=dp[1][1][0][1]=1;
for(i=1; i<=n; ++i)
for(j=1; j<=n; ++j)
if(s[i][j]=='.')
for(kx=0; kx<=k; ++kx)
{
dp[i][j][kx][0]+=dp[i-1][j][kx][0];
if(kx) dp[i][j][kx][0]+=dp[i][j-1][kx-1][1];
dp[i][j][kx][1]+=dp[i][j-1][kx][1];
if(kx) dp[i][j][kx][1]+=dp[i-1][j][kx-1][0];
}
for(kx=0; kx<=k; ++kx)
ans+=(dp[n-1][n][kx][0]+dp[n][n-1][kx][1]);
printf("%lld\n", ans);
}
return 0;
}
