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
*/
posted @ 2026-10-17 18:57  SCX2014  阅读(3)  评论(0)    收藏  举报