查找前驱后继 方法小结
例题:HNOI2012 营业额统计
题目大意:
设排完序后,x的前驱为a,后继为b,求 Σ min(x-a,b-x)
法一:双向链表 64ms 1MB
#include<cstdio> #include<algorithm> using namespace std; int n,rank[40000],pos,ans; struct node { int id,w; int l,r; }e[40000]; bool cmp(node p,node q) { return p.w<q.w; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&e[i].w),e[i].id=i; sort(e+1,e+n+1,cmp); for(int i=1;i<=n;i++) e[i].l=i-1,e[i].r=i+1; e[n].r=0;e[0].w=-1e9; for(int i=1;i<=n;i++) rank[e[i].id]=i; for(int i=n;i>=1;i--) { pos=rank[i]; if(e[pos].l&&e[pos].r) ans+=min(e[pos].w-e[e[pos].l].w,e[e[pos].r].w-e[pos].w); else if(e[pos].l) ans+=e[pos].w-e[e[pos].l].w; else if(e[pos].r) ans+=e[e[pos].r].w-e[pos].w; else ans+=e[pos].w; e[e[pos].r].l=e[pos].l; e[e[pos].l].r=e[pos].r; } printf("%d",ans); }
法二:set 101ms 1MB
#include<cstdio> #include<set> #include<algorithm> using namespace std; set<int>s; int n,x,tmp,l,r,mid,w,k; int ans; int main() { scanf("%d",&n); scanf("%d",&x); s.insert(x); ans+=x; for(int i=1;i<n;i++) { scanf("%d",&x); set<int>::iterator a=s.lower_bound(x); set<int>::iterator b=a; if(a!=s.begin()) a--; if(b==s.end()) b--; ans+=min(abs(x-*a),abs(*b-x)); s.insert(x); } printf("%d",ans); }
法三:splay 90ms 1004KB
#include<cstdio> #include<algorithm> #define N 32770 #define INF 2000000 using namespace std; int root,ans; class splay_tree { private: int pre[N],ch[N][2],key[N],tot; public: inline void newnode(int &r,int fa,int k) { r=++tot; pre[r]=fa; key[r]=k; } inline void rot(int x,int kind) { int y=pre[x]; ch[y][!kind]=ch[x][kind]; pre[ch[x][kind]]=y; ch[x][kind]=y; if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x; pre[x]=pre[y]; pre[y]=x; } inline void splay(int x,int goal) { while(pre[x]!=goal) { int y=pre[x]; int kind=ch[y][0]==x; if(pre[y]==goal) rot(x,kind); else { kind=ch[pre[y]][0]==y; if(ch[y][!kind]==x) { rot(y,kind); rot(x,kind); } else { rot(x,!kind); rot(x,kind); } } } root=x; } inline int insert(int x) { int r=root; while(ch[r][x>key[r]]) { if(x==key[r]) {splay(r,0);return 0;} r=ch[r][x>key[r]]; } if(x==key[r]) {splay(r,0);return 0;} newnode(ch[r][x>key[r]],r,x); splay(ch[r][x>key[r]],0); return 1; } inline int get_pre(int x) { int r=ch[x][0]; if(!r) return -INF; while(ch[r][1]) r=ch[r][1]; return key[r]; } inline int get_suf(int x) { int r=ch[x][1]; if(!r) return INF; while(ch[r][0]) r=ch[r][0]; return key[r]; } }tree; int main() { int n,x; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&x); if(i==1) { ans+=x; tree.newnode(root,0,x); } else { if(!tree.insert(x)) continue; int a=tree.get_pre(root); int b=tree.get_suf(root); ans+=min(x-a,b-x); } } printf("%d",ans); }