zoukankan      html  css  js  c++  java
  • [CSP-S模拟测试]:折纸(模拟)

    题目描述

    小$s$很喜欢折纸。
    有一天,他得到了一条很长的纸带,他把它从左向右均匀划分为$N$个单位长度,并且在每份的边界处分别标上数字$0sim n$。
    然后小$s$开始无聊的折纸,每次他都会选择一个数字,把纸带沿这个数字当前所在的位置翻折(假如已经在边界上了那就相当于什么都不做)。
    小$s$想知道$M$次翻折之后纸带还有多长。


    输入格式

    第一行包含两个正整数$N$和$M$,表示纸带的长度和操作的次数。

    接下来的一行包含$M$个整数$D_i$,其中$D_i$表示第$i$次选择的数字。


    输出格式

    输出文件只有一个数字,即纸带最后的长度。


    样例

    样例输入:

    5 2
    3 5

    样例输出:

    2


    数据范围与提示

    $60\%$的数据中$Nleqslant 3,000,Mleqslant 3,000$。
    $100\%$的数据中$Nleqslant {10}^{18},Mleqslant 3,000$。


    题解

    $60\%$算法:

    直接模拟翻折过程,记录每一个点现在的位置即可,每次暴力更新。

    记得初始化。

    时间复杂度:$Theta(N imes M)$。

    期望得分:$60$分。

    实际得分:$60$分。

    $100\%$算法:

    发现我们并不用关心每个纸带的位置,只用考虑当前操作的位置就好了。

    每次翻折之后对所有的操作进行$Theta(M)$重标号即可,至于式子$D_j=abs(D_i-D_j)$。

    时间复杂度:$Theta(m^2)$。

    期望得分:$100$分。

    实际得分:$100$分。


    代码时刻

    #include<bits/stdc++.h>
    using namespace std;
    long long n,m;
    long long l,r;
    long long wzc[5000];
    int main()
    {
    	scanf("%lld%lld",&n,&m);
    	l=0,r=n;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld",&wzc[i]);
    		for(int j=1;j<i;j++)
    			if(wzc[j]>=wzc[i])
    				wzc[i]=2LL*wzc[j]-wzc[i];
    		r=max(r,2LL*wzc[i]-l);
    		l=wzc[i];
    	}
    	printf("%lld",r-l);
    	return 0;
    }
     

    rp++

  • 相关阅读:
    前端开发中一些好用的软件包。
    LeetCode 26 删除排序数组中的重复项
    算法 主定理
    算法学习计划继续三四个月
    Web Api
    DOM viewport
    CSS OM
    DOM Range Api
    DOM 操作 2
    DOM Event
  • 原文地址:https://www.cnblogs.com/wzc521/p/11366052.html
Copyright © 2011-2022 走看看