[TJOI2011]序列

Posted Excim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[TJOI2011]序列相关的知识,希望对你有一定的参考价值。

原题链接:https://www.luogu.org/problemnew/show/1732

题目大意:已知数列a1,a2...an,数列b1=a1,bi=min(abs(ai-aj))(1<=j<i),换言之,就是找数列a前i-1个数中与ai差最小的数作为bi

用一个vis数组记录那些数字在前i-1项中出现过,读入一个新的ai时,就像两边寻找,因为每一次增加标记相当于把区间分成两部分,不管怎么划分,每一次的寻找次数都不会超过当前最长区间的一半,取最坏情况:l+l/2+l/4+...+l/(2^n)<2*l,也就是每一组数据的时间复杂度是O(l)的,总时间复杂度O(T*l),跟n没有关系。

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
void read(int &y)
{
    y=0;char x=getchar();
    while(x<0||x>9) x=getchar();
    while(x>=0&&x<=9)
    {
        y=y*10+x-0;
        x=getchar();
    }
}
int t,sum,n;
int vis[100005],a[100005]; 
int main()
{
    read(t);
    while(t--)
    {
        memset(vis,0,sizeof(vis)); 
        read(n);
        long long sum;scanf("%lld",&sum);
        vis[sum]=1;
        for(int i=2;i<=n;i++)
        {
            read(a[i]);
            int l=a[i],r=a[i];
            while(1)
            {
                if(vis[l]==1)
                {
                    sum+=a[i]-l;
                    break;
                }
                if(vis[r]==1)
                {
                    sum+=r-a[i];
                    break;
                }
                if(l>0) l--;
                if(r<65536) r++;
            }
            vis[a[i]]=1;
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

以上是关于[TJOI2011]序列的主要内容,如果未能解决你的问题,请参考以下文章

P1377 [TJOI2011]树的序:离线nlogn建二叉搜索树

P4309 [TJOI2013]最长上升子序列

bzoj5157: [Tjoi2014]上升子序列(树状数组LIS)

BZOJ5337 [TJOI2018] 碱基序列 哈希动态规划

TJOI2018 异或

BZOJ 3173: [Tjoi2013]最长上升子序列