zoukankan      html  css  js  c++  java
  • 洛谷 P5639 【CSGRound2】守序者的尊严 题解

    原题链接

    简要题意:

    (1) 号位开始走,可以连续走过一段连续的 (0) ,每走一次,所有位置取反。 (即 (0 gets 1)(1 gets 0)).

    算法一

    模拟暴力即可。

    每次从当前位置模拟往后走到能走的最后一个点(即当前连续 (0) 的最后一个 (0) 的位置),然后暴力将每个位置取反。

    时间复杂度: (O(n^2)).

    实际得分:(50pts).

    算法二

    基于暴力,你可能想到这是线段树?

    可是,这维护的是什么?不可而知。

    每位取反?无法维护。

    连续一段?倒是可以,但是取反维护不了啊……

    所以,算法二 线段树 咕咕咕了。

    算法三

    你会发现,给出的数组必然是这样的一段:

    (0 0 0 0 0 0 ... 1 1 1 ... 0 0 0 ... 1 1 ...)

    也就是,一段连续的 (0) 和 一段连续的 (1) 交错而成。

    我们需要跳开修改,解决问题。

    以样例为例:

    (0 0 1 1 0 1)

    我们第一次走到 (2) 的位置,然后变成:

    (1 1 0 0 1 0)

    你会发现,如果不修改的话,其实你只要再走一段连续的 (1) ,和修改后走一段连续的 (0) 是一样的。

    走到 (4) 的位置,然后变成:

    (0 0 1 1 0 1)

    你会发现,如果不修改的话,其实你只要再走一段连续的 (0) ,和修改后走一段连续的 (1) 是一样的。

    所以,第偶数步我们走连续的 (0) ,奇数步走连续的 (1) ,模拟一遍。

    时间复杂度: (O(n)).

    实际得分: (100pts).

    算法四

    显然我们考虑另一个常数性的优化。

    你会发现,你并不在乎 连续的一段有多少个 ,而关心 一共有多少段 ,这就是我们的答案。

    那么,总段数其实就是 (a_i ot = a_{i-1}) 的个数再 (+1) .

    很好理解:一开始只有一段,每改变一次就产生新的一段。

    显然,这个无论从码量,时间都比算法三要优一些。

    时间复杂度: (O(n)).

    实际得分: (100pts).

    #pragma GCC optimize(2)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=1e6+1;
    
    inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
    	int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
    
    int n,a[N];
    int s=0;
    
    int main(){
    	n=read();
    	for(int i=1;i<=n;i++) a[i]=read();
    	for(int i=2;i<=n;i++) s+=(a[i]!=a[i-1]);
    	printf("%d
    ",s+1);
    	return 0;
    }
    
    
  • 相关阅读:
    HTML和XHTML知识总结
    理解margin-left:-100%
    git clean的用法
    vue路由传参的三种基本方式
    vertical-align属性
    纯CSS制作各种图形(多图预警)
    css伪元素:before和:after用法详解
    前端注册登录的业务流程
    Vue-cli 中为单独页面设置背景图片铺满全屏的方法
    vscode 开启对 webpack alias(文件别名) 引入的智能提示
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12503990.html
Copyright © 2011-2022 走看看