P16857 [GKS 2021 #F] Trash Bins 题解
题目大意
街上有 \(N\) 栋房子,有些房子前有垃圾桶,有些没有,求每个房子的主人倒垃圾所需行走的距离之和。
算法分析
门前有垃圾桶的不用考虑,因为他一步都不用走。
考虑将连续门前没有垃圾桶的划分为一个团体,将这个团体分成两类:第一种,团体右边或左边没有垃圾桶,也就是说这个团体在边缘,那么这个团体显然只能到左边或右边的垃圾桶倒垃圾,设长度为 \(L\),那么这个团体的贡献值为 \(\frac{L(L+1)}{2}\);第二种,左边右边都有垃圾桶,那么这个团体会选择两边更近的一个垃圾桶,怎么算呢?考虑将这个团体分成两块,一块是离左边垃圾桶更近的,另一块是离右边垃圾站更近的,设团队长度为 \(L\),离左边垃圾桶更近的块长为 \(l\),那么这个团队的贡献值为 \(\frac{l(l+1)}{2}+\frac{(L-l)(L-l+1)}{2}\)。
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
int f[N];
int main(){
std::ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int T,id=0;
cin>>T;
while(T--){
cout<<"Case #"<<++id<<": ";
int n;
cin>>n;
for(int i=1;i<=n;i++){
char x;
cin>>x;
if(x=='1')f[i]=1;
else f[i]=0;
}
long long ans=0;
int l=0,r=n+1;
long long num=0;
for(int i=1;i<=n;i++){//第一种情况
if(f[i])break;
num++,l=i;
}
ans+=num*(num+1)/2;
num=0;
for(int i=n;i>=1;i--){
if(f[i])break;
num++,r=i;
}
ans+=num*(num+1)/2;
num=0;
for(int i=l+1;i<r;i++){//第二种情况
if(f[i]){
ans+=(num/2)*(num/2+1)/2+(num-num/2)*(num-num/2+1)/2;
num=0;
}else{
num++;
}
}
cout<<ans<<'\n';
}
return 0;
}
/*
1 2 3 4 5 6 7 8 9
1 2 4 6 9 12 16 20 25
*/

浙公网安备 33010602011771号