zoukankan      html  css  js  c++  java
  • BZOJ 1588:营业额统计(Splay)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1588

    题意:中文题意。

    思路:每一个点每一个点插入Splay,然后插入新的一个点之后,查这个节点的前驱和后继,即左子树最右边的点和右子树最左边的点。然后再从两个点中取个差值较小的就是答案了。要注意Rotate的时候一些细节(要给 rt 的父亲的父亲更新其孩子的值),还有Splay的细节:如果 rt 和 父节点都是要旋转相同方向,应该先旋转父亲节点再旋 rt,如果旋转不同方向就都是旋 rt。

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <cstring>
      5 #include <string>
      6 #include <cmath>
      7 #include <queue>
      8 #include <vector>
      9 using namespace std;
     10 #define INF 0x7fffffff
     11 #define N 40000
     12 struct node
     13 {
     14     int val, fa, son[2]; // val是节点权值,fa是父亲,son[0]是左儿子, son[1]是右儿子
     15 }tree[N];
     16 int cnt; // 节点数
     17 
     18 void new_node(int f, int w, int kind)
     19 {
     20     cnt++;
     21     memset(tree[cnt].son, 0, sizeof(tree[cnt].son));
     22     tree[cnt].val = w;
     23     tree[cnt].fa = f;
     24     tree[f].son[kind] = cnt;
     25 }
     26 
     27 void Rotate(int rt, int kind) // 旋转操作要注意更新 rt 的父亲的父亲的儿子的值
     28 {
     29     int y = tree[rt].fa;
     30     tree[y].son[kind^1] = tree[rt].son[kind];
     31     if(tree[rt].son[kind] != 0) tree[tree[rt].son[kind]].fa = y;
     32     tree[rt].fa = tree[y].fa;
     33     int z = tree[rt].fa;
     34     if(tree[z].son[0] == y) tree[z].son[0] = rt; // 就是这里
     35     else tree[z].son[1] = rt;
     36     tree[rt].son[kind] = y;
     37     tree[y].fa = rt;
     38 }
     39 
     40 void Splay(int rt, int goal)
     41 {
     42     if(tree[rt].fa == goal) return ;
     43     while(tree[rt].fa != goal) {
     44         int y = tree[rt].fa;
     45         int z = tree[y].fa;
     46         int kind1 = rt == tree[y].son[0] ? 1 : 0;
     47         int kind2 = y == tree[z].son[0] ? 1 : 0;
     48         if(z == goal) {
     49             Rotate(rt, kind1);
     50         } else {
     51             if(kind1 == kind2) { // 连续左旋或者右旋
     52                 Rotate(y, kind2);
     53             } else {
     54                 Rotate(rt, kind1); // 先左后右或者先右后左
     55             }
     56             Rotate(rt, kind2);
     57         }
     58     }
     59 }
     60 
     61 void Insert(int rt, int fa, int val, int kind)
     62 {
     63     if(rt == 0) {
     64         new_node(fa, val, kind);
     65         return ;
     66     }
     67     if(tree[rt].val >= val) Insert(tree[rt].son[0], rt, val, 0);
     68     else Insert(tree[rt].son[1], rt, val, 1);
     69 }
     70 
     71 int Find(int rt, int kind)
     72 {
     73     if(tree[rt].son[kind] == 0) return rt; // 查先驱和后继节点
     74     Find(tree[rt].son[kind], kind);
     75 }
     76 
     77 int main()
     78 {
     79     int n;
     80     while(~scanf("%d", &n)) {
     81         long long ans = 0;
     82         cnt = 0;
     83         for(int i = 1; i <= n; i++) {
     84             int x;
     85             scanf("%d", &x);
     86             if(i == 1) {
     87                 new_node(0, x, 0);
     88                 ans += x;
     89             } else {
     90                 Insert(cnt, 0, x, 0);
     91                 Splay(cnt, 0);
     92                 int pre = 0, suf = 0;
     93                 pre = Find(tree[cnt].son[0], 1);
     94                 suf = Find(tree[cnt].son[1], 0);
     95                 int prev = INF, sufv = INF;
     96                 if(pre != 0) prev = tree[pre].val;
     97                 if(suf != 0) sufv = tree[suf].val;
     98                 ans += min(abs(x - prev), abs(x - sufv));
     99             }
    100         }
    101         printf("%lld
    ", ans);
    102     }
    103     return 0;
    104 }
  • 相关阅读:
    [转]简单理解php的socket编程
    github 生成token的方法
    win7升级powershell【转】
    PHP的反射机制 【转】
    jquery幻灯片插件slick演示
    织梦生成的时候“你指定的文件名有问题,无法创建文件”解决方案【转】
    dedecms下的tplcache模板缓存[转]
    dede织梦data目录正确迁移及引起的问题解决方法【转】
    C# 判断是否是在设计模式下有效的方法
    C# 操作计算机用户权限
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6053921.html
Copyright © 2011-2022 走看看