• 洛谷 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;
    }
    
    
  • 相关阅读:
    老板说,你给我1分钟内下载100张图片!So,easy!
    测试用例 setup 和 和 teardown
    pytest环境准备与入门
    测试工程需要明白的Monkey测试
    5.通过定位实现二级菜单
    4.CSS中float导致的高度坍塌问题及解决方法
    3.使用float实现文字环绕图片
    2.reset.css文件
    1.图片元素<img>和<map>的联用
    1.引用js文件中的函数调用
  • 原文地址:https://www.cnblogs.com/bifanwen/p/12503990.html
Copyright © 2020-2023  润新知