原题链接: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 ",sum); } return 0; }