zoukankan      html  css  js  c++  java
  • 题解 CF1428F Fruit Sequences

    ( exttt{Bullshit})

    蒟蒻 ( exttt{7 min})( exttt{F}), 挽回了本一定掉分的局面/cy
    qwq.png
    分竟然还没有别人 5 题高

    (本题解为目前 cf 上的最短代码解!)

    ( exttt{Solution})

    考虑计算对于每一个左端点的贡献。

    所以可以考虑算这个左端点比后面的那个左端点多了多少贡献。

    对于一个位置 (l) :

    1. 这个位置是 0 : 没有多余贡献。
    2. 这个位置是 1 : 如果这个位置到这个联通块底部的长度为 (k), 那么找到后面第一个出现连通块长度为 (k) 的位置 (d),那么右端点在 ([l, d - 1]) 的答案都会加一,比左端点为 (l+1) 的贡献多了 (d - l); 如果找不到,右端点在 ([d, n]) 的答案都会加一,那么比左端点为 (l+1) 的贡献多了 (n + 1 - l)

    给一张图以便理解:

    Codeforces-Fruit.png

    然后考虑怎么维护这东西。

    由于我们要找的是第一个出现某联通块长的位置, 那么我们可以在计算完长度为 (k), 初始位置为 (t) 的连通块的贡献后,从左到右更新联通块长度为 (1)(k) 的第一次出现的位置。长度为 (p) 第一次出现的位置更新为 (t + p - 1)

    因此直接用数组维护就好啦!

    ( exttt{Code})

    不是给人看的代码:

    #include<cstdio>
    int n,f[555555],now;long long ans,sum;char s[555555];int main(){scanf("%d%s",&n,s+1);for(int i=n;i>=1;i--){if(s[i]-'0')now++,sum+=(!f[now]?n+1:f[now])-i;else while(now)f[now]=i+now,now--; ans+=sum;}printf("%lld
    ", ans);}
    

    给人看的代码:

    #include<bits/stdc++.h>
    const int N = 1e6 + 7;
    int n, f[N], now; 
    // f[i] : 记录联通块大小为 i 的第一次出现的位置 
    // now : 记录现在的连通块大小 
    long long  ans, sum;
    // ans : 记录答案
    // sum : 目前这个左端点的答案 
    char s[N];
    int main() {
    	scanf("%d%s", &n, s + 1);
    	for(int i = 1; i <= n; i++) f[i] = n + 1;
    	for(int i = n; i >= 1; i--) {
    		if(s[i] - '0') now++, sum += f[now] - i; // 联通块大小++, 计算比左端点为 i + 1 的贡献多了多少 
    		else while(now) f[now] = i + now, now--; // 一个连通块的结束,更新 f 的值 
    		ans += sum; 
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    JQuery优化之 -- 正确使用选择器
    Vue计算属性methords 与 computed 的区别
    HTML中常用字符实体
    SQL复习(w3school)笔记
    AndroidStudio中使用AndroidAnnotations时,build.gradle的配置
    JAVA的第一次作业
    input标签submit属性,用CSS控制样式时高度不好控制的解决办法
    微信小程序开发五:案例实践
    微信小程序开发四:接口
    微信小程序开发三:组件
  • 原文地址:https://www.cnblogs.com/zkyJuruo/p/13833960.html
Copyright © 2011-2022 走看看