1588: [HNOI2002]营业额统计 splay tree

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

//题意:每读入一个数,在前面输入的数中找到一个与该数相差最小的一个,把所有的差值绝对值加起来并输出

  1 #include "bits/stdc++.h"
  2 using namespace std;
  3 const int maxn = 100010;
  4 const int INF = 0x3f3f3f3f;
  5 struct SplayTreeNode
  6 {
  7     int key;
  8     int father, child[2];
  9 }splayTreeNode[maxn];
 10 int splayTreeRoot, cntSplayTreeNode;
 11 
 12 int n, num;
 13 
 14 void AddSonNode(int &son, int father, int key)
 15 {
 16     ++cntSplayTreeNode;
 17     son = cntSplayTreeNode;
 18     splayTreeNode[son].key = key;
 19     splayTreeNode[son].father = father;
 20     splayTreeNode[son].child[0] = splayTreeNode[son].child[1] = 0;
 21 }
 22 
 23 void Rotate(int index, bool pos)
 24 {
 25     int indexFather = splayTreeNode[index].father;
 26     int indexFatherFather = splayTreeNode[indexFather].father;
 27     int indexSon = splayTreeNode[index].child[!pos];
 28     //父节点 子节点
 29     splayTreeNode[ indexFather ].child[pos] = indexSon;
 30     splayTreeNode[ indexSon ].father = indexFather;
 31     //父节点的父节点 原节点
 32     if(indexFatherFather) {
 33         bool posFather = splayTreeNode[ indexFatherFather ].child[1] == indexFather;
 34         splayTreeNode[ indexFatherFather ].child[posFather] = index;
 35     }
 36     splayTreeNode[index].father = splayTreeNode[indexFather].father;
 37     //原节点 父节点
 38     splayTreeNode[index].child[!pos] = indexFather;
 39     splayTreeNode[indexFather].father = index;
 40 }
 41 
 42 void Splay(int index, int goalFather)
 43 {
 44     int indexFather;
 45     while((indexFather = splayTreeNode[index].father) != goalFather) {
 46         bool pos = splayTreeNode[indexFather].child[1] == index;
 47         //旋转一次能达到目的
 48         if(splayTreeNode[indexFather].father == goalFather) {
 49             Rotate(index, pos);
 50         }
 51         else {
 52             bool posFather = splayTreeNode[ splayTreeNode[indexFather].father ].child[1] == indexFather;
 53             if(pos != posFather) {
 54                 //方位不同,子节点旋转两次
 55                 Rotate(index, pos);
 56                 Rotate(index, posFather);
 57             }
 58             else {
 59                 //方位相同,先旋转父节点,再旋转子节点
 60                 Rotate(indexFather, pos);
 61                 Rotate(index, pos);
 62             }
 63         }
 64     }
 65     //旋转到备用节点 0 下方,则为根节点
 66     if(goalFather == 0)
 67         splayTreeRoot = index;
 68 }
 69 
 70 //失败返回 0,成功返回 1
 71 bool InsertNode(int key)
 72 {
 73     int index = splayTreeRoot;
 74     while(splayTreeNode[index].child[ splayTreeNode[index].key < key ]) {
 75         //不重复插入
 76         if(splayTreeNode[index].key == key) {
 77             //旋转到根节点
 78             Splay(index, 0);
 79             return 0;
 80         }
 81         index = splayTreeNode[index].child[ splayTreeNode[index].key < key ];
 82     }
 83     AddSonNode(splayTreeNode[index].child[ splayTreeNode[index].key < key ], index, key);
 84     Splay(splayTreeNode[index].child[ splayTreeNode[index].key < key ], 0);
 85     return 1;
 86 }
 87 
 88 int getColost_1(int index)
 89 {
 90     int indexSon = splayTreeNode[index].child[0];
 91     if(indexSon == 0)
 92         return INF;
 93     while(splayTreeNode[indexSon].child[1])
 94         indexSon = splayTreeNode[indexSon].child[1];
 95     return splayTreeNode[index].key - splayTreeNode[indexSon].key;
 96 }
 97 
 98 int getColost_2(int index)
 99 {
100     int indexSon = splayTreeNode[index].child[1];
101     if(indexSon == 0)
102         return INF;
103     while(splayTreeNode[indexSon].child[0])
104         indexSon = splayTreeNode[indexSon].child[0];
105     return -splayTreeNode[index].key + splayTreeNode[indexSon].key;
106 }
107 
108 int main()
109 {
110     int i;
111     while(scanf("%d", &n) != EOF) {
112         splayTreeRoot = cntSplayTreeNode = 0;
113         int res = 0;
114         for(i = 1; i <= n; ++i) {
115             if(scanf("%d", &num) == EOF)   //数据有些问题,要加上这个
116                 num = 0;
117             if(i == 1) {
118                 res += num;
119                 AddSonNode(splayTreeRoot, 0, num);
120                 continue;
121             }
122             if(InsertNode(num) == 0)
123                 continue;
124             int tmp_1 = getColost_1(splayTreeRoot);
125             int tmp_2 = getColost_2(splayTreeRoot);
126             res += min(tmp_1, tmp_2);
127         }
128         printf("%d\n", res);
129     }
130 }

//窝只是想给程序的加一点可读性...没想到写成了这个鬼样子QAQ

转载于:https://www.cnblogs.com/AC-Phoenix/p/4430143.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[2\]的描述,题目中的影魔拥有n个灵魂,每个灵魂有一个战斗力ki。对于任意一对灵魂对i,j (i<j),如果不存在ks (i<s<j)大于ki或者kj,则会为影魔提供p1的攻击力。另一种情况是,如果存在一个位置k,满足ki<c<kj或者kj<c<ki,则会为影魔提供p2的攻击力。其他情况下的灵魂对不会为影魔提供攻击力。 根据引用\[3\]的描述,我们可以从左到右进行枚举。对于情况1,当扫到r\[i\]时,更新l\[i\]的贡献。对于情况2.1,当扫到l\[i\]时,更新区间\[i+1,r\[i\]-1\]的贡献。对于情况2.2,当扫到r\[i\]时,更新区间\[l\[i\]+1,i-1\]的贡献。 因此,对于给定的区间\[l,r\],我们可以根据上述方法计算出区间内所有下标二元组i,j (l<=i<j<=r)的贡献之和。 #### 引用[.reference_title] - *1* *3* [P3722 [AH2017/HNOI2017]影魔(树状组)](https://blog.csdn.net/li_wen_zhuo/article/details/115446022)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [洛谷3722 AH2017/HNOI2017 影魔 线段树 单调栈](https://blog.csdn.net/forever_shi/article/details/119649910)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值