Codeforces Round #547 C. Polycarp Restores Permutation(二分枚举/数学+模拟)

在这里插入图片描述

题意: 有一个长度为N的序列p,该序列保证存在1~N每个值都存在,现在给出一个序列q,长度为N-1,表示序列p相邻两数之差,根据序列q输出序列p

题解: 一开始想复杂了,以为要找什么最大差值最小差值来扩展,又或者枚举的话可能因为不断尝试的过程需要递归搜索,复杂度会很大。。。。

边界条件永远是 1 ~ N

一开始用for循环枚举判断每个值,这个复杂度可能是O(N*N)的,最复杂情况,当2e5个差值是等差序列,差值为1,但是最后一个值的差值存在巨大异常,那么枚举的范围将是2e5,而得到不合法序列的时间将是计算到最后才知道。【第41组case】

考虑两个优化,首先我们知道,在差值确定的情况下,当我们重复计算出某个值的时候,无论枚举任何数,都会出现重复值,因为题意是必须出现1~N所有值,因此不可能出现重复值,一旦出现重复值,就不继续构造该序列,直接无解。

第二个也是最重点的优化,即for枚举改成二分枚举,因为可以知道,当计算一个值出现不合法情况是,如计算出来的值是大于N的或小于0的,可以根据结果调整枚举值的范围,想象该序列是一段折线,那么当某个值大于N时,我们将枚举的第一个值向下调整,当小于0时,第一个值向上调整,那么整个序列都将上移,二分枚举不断找到一个令所有值都合法的序列
在这里插入图片描述
最后复杂度,O(N*logN)
代码如下:

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn=2e5+7;
int n,q[maxn];
bool vis[maxn<<1];
vector<int>p;
int main()
{
   
    scanf("%d",&n);
    bool flag=false,gg=false;
    for(int i=1; i<n; i++)scanf("%d",&q[i]);
    int l=1,r=n;
    while(l<=r)
    {
   
        int i=(l+r)
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值