BZOJ1588 [HNOI2002]营业额统计
裸splay,最近刚学了一下。下面是一篇关于学splay的很不错的文章
http://wenku.baidu.com/view/a202e27931b765ce05081416.html
现在只看到了插入操作。到目前为止发现了这篇文章两个错误的地方
第一个是在splay函数里的22行,应该是左旋
第二个是在插入函数里的28行应该是对tot(也就是当前节点)进行伸展操作
对于这道题,每读入一个数,插入进去之后,在其左子树里查找最大值,在右子树里查找最小值,即当前值相差最小的两个节点。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 const int maxn = 40005; 7 const int INF = 0x3f3f3f3f; 8 int fa[maxn],son[2][maxn],val[maxn]; 9 int root,tot; 10 void rota(int w,int x){ 11 int y = fa[x]; 12 son[!w][y] = son[w][x]; 13 if(son[w][x])fa[son[w][x]] = y; 14 fa[x] = fa[y]; 15 if(fa[y])son[y==son[1][fa[y]]][fa[y]] = x; 16 son[w][x] = y;fa[y] = x; 17 } 18 void splay(int x,int y){ 19 while(fa[x]!=y){ 20 if(fa[fa[x]]==y)rota(x==son[0][fa[x]],x); 21 else { 22 int w = fa[x]==son[0][fa[fa[x]]]; 23 if(x==son[w][fa[x]]){ 24 rota(!w,x); 25 rota(w,x); 26 } 27 else { 28 rota(w,fa[x]); 29 rota(w,x); 30 } 31 } 32 } 33 if(!y)root = x; 34 } 35 int insert(int v){ 36 int x = root; 37 while(1){ 38 if(v==val[x]){splay(x,0);return 0;} 39 if(v<val[x]){ 40 if(son[0][x])x = son[0][x]; 41 else break; 42 } 43 else { 44 if(son[1][x])x = son[1][x]; 45 else break; 46 } 47 } 48 fa[++tot] = x; 49 val[tot] = v; 50 if(v<val[x])son[0][x] = tot; 51 else son[1][x] = tot; 52 splay(tot,0); 53 return 1; 54 } 55 int getfa(){ 56 int x =son[0][root]; 57 if(x==0)return INF; 58 while(son[1][x])x = son[1][x]; 59 return val[x]; 60 } 61 int getson(){ 62 int x = son[1][root]; 63 if(x==0)return INF; 64 while(son[0][x])x = son[0][x]; 65 return val[x]; 66 } 67 int main() 68 { 69 int ans = 0,n;scanf("%d",&n); 70 for(int i = 1;i<=n;++i){ 71 int t;if(scanf("%d",&t)==EOF)t = 0; 72 if(i==1){ 73 root = ++tot; 74 val[tot] = t; 75 ans+=t; 76 continue; 77 } 78 if(insert(t)==0)continue; 79 int a = getfa(),b = getson(); 80 ans+=min(abs(a-t),abs(b-t)); 81 } 82 printf("%d\n",ans); 83 return 0; 84 }
弱者究竟为何而战?!