题解:

我们发现,今天的波动=min(x-pre,nxt-x)

所以可以维护一颗平衡树

模板前驱后继即可

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
int in[2*N],pre[N],data[N],tot,size[N],c[N][2],root,n,x;
void rot(int x)
{
    int y=pre[x],k=(x==c[y][0]);
    size[k]=size[c[y][k]]+size[c[x][k]]+1;
    size[x]=size[c[x][!k]]+size[y]+1;
    c[y][!k]=c[x][k];
    pre[c[y][!k]]=y;
    pre[x]=pre[y];
    if (pre[y])c[pre[y]][c[pre[y]][1]==y]=x;
    c[x][k]=y;pre[y]=x;
} 
void splay(int x,int g)
{
    for (int y=pre[x];y!=g;rot(x),y=pre[x])
     if (pre[y]!=g)rot((x==c[y][0])==(y==c[pre[y]][0])?y:x);
    if (g==0)root=x;
}
void inster(int x)
{
    int y=root;
    while (c[y][x>data[y]])y=c[y][x>data[y]];
    data[++tot]=x;
    c[tot][0]=c[tot][1]=0;
    pre[tot]=y;
    if (y)c[y][x>data[y]]=tot;
    splay(tot,0);
}
int findpre(int x)
{
    int ans;
    for (int y=root;y;)
     if (data[y]<x)ans=data[y],y=c[y][1];
     else y=c[y][0];
    return ans; 
}
int findnxt(int x)
{
    int ans;
    for (int y=root;y;)
     if (data[y]<x)y=c[y][1];
     else ans=data[y],y=c[y][0];
    return ans; 
}
int main()
{
    scanf("%d%d",&n,&x);
    inster(x+N);in[x+N]=1;
    int ans=x,S=x+N,B=x+N;
    for (int i=1;i<n;i++)
     {
         scanf("%d",&x);x+=N;
         if (in[x])continue;
         int k=1e9;
         if (x>S)k=min(k,x-findpre(x));
         if (x<B)k=min(k,findnxt(x)-x);
         ans+=k;S=min(S,x);B=max(B,x);
         inster(x);in[x]=1;
     }
    printf("%d",ans); 
}

 

posted on 2017-11-21 18:49  宣毅鸣  阅读(162)  评论(0编辑  收藏  举报