【BZOJ2809】【splay启发式合并】dispatching

本文介绍了一种基于树形结构的算法,用于解决如何在预算范围内最大化顾客满意度的问题。通过使用Splay树来高效地处理忍者团队的派遣与管理问题。

Description

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。

 

1  ≤N ≤ 100,000 忍者的个数;
1  ≤M ≤ 1,000,000,000 薪水总预算; 
 
0  ≤Bi < i  忍者的上级的编号;
1  ≤Ci ≤ M                     忍者的薪水;
1  ≤Li ≤ 1,000,000,000             忍者的领导力水平。

Input

从标准输入读入数据。
 
第一行包含两个整数 N M,其中 N表示忍者的个数,M表示薪水的总预算。
 
接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整 Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力。Master满足B i = 0并且每一个忍者的老板的编号一定小于自己的编号 Bi < i

Output

输出一个数,表示在预算内顾客的满意度的最大值。
 
 

Sample Input


5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1

Sample Output

6

HINT

如果我们选择编号为 1的忍者作为管理者并且派遣第三个和第四个忍者,薪水总和为 4,没有超过总预算                         4。因为派遣了                              2   个忍者并且管理者的领导力为      3,

用户的满意度为 2      ,是可以得到的用户满意度的最大值。

Source

【分析】

什么启发式合并。叫得这么高端...不就是一个个插进去吗....

记得要用longlong

发现了一个很严重的问题,昨天的splay里面有问题。。

还是指针的问题....如果没有用引用的话就要返回,否则的话值不会变,貌似这个问题只有在以大小作为排序标准的情况下才会出现?

因为好像splay处理序列的时候一般是不需要根据大小排序的,所以一直没有发现....还好发现了,不然省选出现这个问题就跪了啊!!

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <vector>
  6 #include <utility>
  7 #include <iomanip>
  8 #include <string>
  9 #include <cmath>
 10 #include <queue>
 11 #include <assert.h>
 12 #include <map>
 13 #include <ctime>
 14 #include <cstdlib>
 15 #include <stack>
 16 #define LOCAL
 17 const int MAXN = 1020000 + 10;
 18 const int INF = 100000000;
 19 const int SIZE = 450;
 20 const int maxnode =  0x7fffffff + 10;
 21 using namespace std;
 22 vector<long long>G[MAXN];
 23 stack<long long>S;
 24 long long n;
 25 long long b[MAXN];
 26 long long c[MAXN], l[MAXN], m;
 27 
 28 struct SPLAY{
 29        struct Node{ 
 30               long long size;
 31               long long val, sum;
 32               Node *parent, *ch[2];
 33               
 34               long long cmp(){
 35                   if (parent->ch[0] == this) return 0;
 36                   else return 1;
 37               }
 38        }*nil, _nil, mem[MAXN], *root[MAXN];
 39        long long tot, pos;//pos表示当前根是哪一个 
 40        
 41        void update(Node *&t){
 42             if (t == nil) return;
 43             t->size = 1;
 44             t->size += t->ch[0]->size + t->ch[1]->size;
 45             t->sum = t->val;
 46             t->sum += t->ch[0]->sum + t->ch[1]->sum;
 47             return;
 48        }
 49        void init(){
 50             //循环哨兵 
 51             nil = &_nil;
 52             _nil.val = _nil.size =_nil.sum = 0;
 53             _nil.parent = _nil.ch[0] = _nil.ch[1] = nil;
 54             
 55             tot = 0;
 56             //没有根就只能加一点特判断了 
 57        }
 58        Node *NEW(long long val){
 59             Node *p = &mem[tot++];
 60             p->size = 1;
 61             p->val = p->sum = val;
 62             p->parent = p->ch[0] = p->ch[1] = nil;
 63             return p; 
 64        }
 65        //旋转,d代表1右旋 
 66        void Rotate(Node *t, long long d){
 67             Node *p = t->parent;
 68             t = p->ch[d ^ 1];
 69             p->ch[d ^ 1] = t->ch[d];
 70             if (t->ch[d] != nil) t->ch[d]->parent = p;
 71             t->ch[d] = p;
 72             t->parent = p->parent;
 73             //注意不是引用 
 74             if (t->parent != nil){
 75                if (t->parent->ch[0] == p) t->parent->ch[0] = t;
 76                else t->parent->ch[1] = t;
 77             }
 78             p->parent = t;
 79             if (t->parent == nil) root[pos] = t;
 80             update(p);
 81             update(t);
 82        }
 83        //没标记就是好TAT 
 84        Node* splay(Node *x, Node *y){
 85             while (x->parent != y){
 86                   if (x->parent->parent == y){
 87                      Rotate(x, x->cmp() ^ 1);
 88                      break;
 89                   }else{
 90                      Rotate(x->parent, x->parent->cmp() ^ 1);
 91                      Rotate(x, x->cmp() ^ 1);
 92                   }
 93                   update(x);
 94             }
 95             update(x);
 96             return x;
 97        } 
 98        void insert(Node *&t, long long val){
 99             if (t == nil){
100                   t = NEW(val);
101                   return;
102             } 
103             Node *x = t;
104             Node *y = t;
105             while (1){
106                   long long d = (val >= x->val);
107                   if (x->ch[d] == nil){
108                      x->ch[d] = NEW(val);
109                      x->ch[d]->parent = x;
110                      //update(x);
111                      t = splay(x->ch[d], nil);  
112                      return;
113                   }else {x = x->ch[d];}
114             }
115             return;//不用update 
116        }
117        void push(Node *&t){
118             if ( t == nil) return;
119             push(t->ch[1]);
120             S.push(t->val);
121             push(t->ch[0]);
122        }
123        //感动天地没有find! 
124        Node* merge(Node *a, Node *b, long long pa, long long pb){
125             if (a == nil) return b;
126             else if (b == nil) return a;
127             //注意是将b插入a,为了启发式合并要判断大小 
128             if (a->size < b->size){
129                //swap(root[pa], root[pb]);
130                swap(a, b);
131             }
132             push(b);//把p推到栈里面 
133             while (!S.empty()){
134                   insert(a, S.top());
135                   S.pop();
136             }
137             //delete b;//可以删掉吧.... 
138             return a;
139        }
140 
141        //表示在Node*t中sum比m小 
142        long long get(Node *t, long long val){
143            Node *x = t;
144            long long cnt = 0;
145            while (1){
146                  if (x == nil) break;
147                  if (val >= x->sum) {cnt += x->size; break;}//一次性全部拿完,包括子树 
148                  //能往左走当然尽量往左 
149                  long long tmp = (x->ch[0]->sum);
150                  //拿完左子树去右边拿 
151                  if (val >= (tmp + x->val)) {cnt += x->ch[0]->size + 1; val -= tmp + x->val; x = x->ch[1];}
152                  else x = x->ch[0];//往左边拿 
153            }
154            return cnt;
155        }
156        void work(){
157             init();
158             while (!S.empty()) S.pop(); 
159             long long Ans = 0;
160             for (long long i = n; i >= 1; i--){
161                 if (G[i].size() == 0){//叶子节点 
162                    root[i] = NEW(c[i]);
163                    if (c[i] <= m) Ans = max(Ans, l[i]);
164                    continue;
165                 }
166                 if (i == 3){
167                    //prlong long(root[8]);
168                    //printf("\n\n\n");
169                 }
170                 root[i] = nil;//枚举每个管理者 
171                 pos = i;
172                 insert(root[i], c[i]);
173                 for (long long j = 0; j < G[i].size(); j++){
174                    long long v = G[i][j];
175                    root[i] = merge(root[i], root[G[i][j]], i, v);
176                    if (i == 3){
177                         // prlong long(root[3]);
178                          //printf("\n\n\n");
179                       }
180                 }
181                 //printf("%d\n", tot);
182                 //if ((get(root[i], m) * l[i]) == 12)
183                 //printf("");
184                 if (i == 8){
185                    //printf("%d", root[3]->size);
186                    //prlong long(root[8]);
187                 }
188                 Ans = max(Ans, get(root[i], m) * l[i]);
189             }
190             /*pos = n;
191             insert(root[n], 10);
192             insert(root[n], 1);*/
193             printf("%lld\n", Ans);
194             //printf("%d", tot);
195        }
196        /*void print(Node *t){
197             if (t == nil) return ;
198             prlong long(t->ch[0]);
199             printf("%lld %lld\n", t->val, t->parent->val);
200             prlong long(t->ch[1]);
201        }*/
202        void debug(){
203             init();
204             Node *p = NEW(5);
205             insert(p, 3);
206             printf("%lld", p->val);
207        }
208 }A;
209 
210 
211 void read(){
212      //memest
213      long long sum = 0;
214      scanf("%lld%lld", &n, &m);//m为薪水总预算 
215      for (long long i = 1; i <= n; i++){
216          //分别代表上级薪水领导力
217          scanf("%lld%lld%lld", &b[i], &c[i], &l[i]);
218          G[b[i]].push_back(i);
219          //sum += c[i];
220          //printf("%d %lld %d\n", b[i], c[i], (2568 / 428));
221      }
222      //第3个有6个 
223      //printf("%d\n", m);
224 }
225 
226 int main(){
227     
228     read();
229     A.work();
230     //A.debug();
231     return 0;
232 }
View Code

 

转载于:https://www.cnblogs.com/hoskey/p/4332788.html

下载前可以先看下教程 https://pan.quark.cn/s/a4b39357ea24 在网页构建过程中,表单(Form)扮演着用户与网站之间沟通的关键角色,其主要功能在于汇集用户的各类输入信息。 JavaScript作为网页开发的核心技术,提供了多样化的API和函数来操作表单组件,诸如input和select等元素。 本专题将详细研究如何借助原生JavaScript对form表单进行视觉优化,并对input输入框与select下拉框进行功能增强。 一、表单基础1. 表单组件:在HTML语言中,<form>标签用于构建一个表单,该标签内部可以容纳多种表单组件,包括<input>(输入框)、<select>(下拉框)、<textarea>(多行文本输入区域)等。 2. 表单参数:诸如action(表单提交的地址)、method(表单提交的协议,为GET或POST)等属性,它们决定了表单的行为特性。 3. 表单行为:诸如onsubmit(表单提交时触发的动作)、onchange(表单元素值变更时触发的动作)等事件,能够通过JavaScript进行响应式处理。 二、input元素视觉优化1. CSS定制:通过设定input元素的CSS属性,例如border(边框)、background-color(背景色)、padding(内边距)、font-size(字体大小)等,能够调整其视觉表现。 2. placeholder特性:提供预填的提示文字,以帮助用户明确输入框的预期用途。 3. 图标集成:借助:before和:after伪元素或者额外的HTML组件结合CSS定位技术,可以在输入框中嵌入图标,从而增强视觉吸引力。 三、select下拉框视觉优化1. 复选功能:通过设置multiple属性...
【EI复现】基于深度强化学习的微能源网能量管理与优化策略研究(Python代码实现)内容概要:本文围绕“基于深度强化学习的微能源网能量管理与优化策略”展开研究,重点探讨了如何利用深度强化学习技术对微能源系统进行高效的能量管理与优化调度。文中结合Python代码实现,复现了EI级别研究成果,涵盖了微电网中分布式能源、储能系统及负荷的协调优化问题,通过构建合理的奖励函数与状态空间模型,实现对复杂能源系统的智能决策支持。研究体现了深度强化学习在应对不确定性可再生能源出力、负荷波动等挑战中的优势,提升了系统运行的经济性与稳定性。; 适合人群:具备一定Python编程基础和机器学习背景,从事能源系统优化、智能电网、强化学习应用等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①应用于微能源网的能量调度与优化控制,提升系统能效与经济效益;②为深度强化学习在能源管理领域的落地提供可复现的技术路径与代码参考;③服务于学术研究与论文复现,特别是EI/SCI级别高水平论文的仿真实验部分。; 阅读建议:建议读者结合提供的Python代码进行实践操作,深入理解深度强化学习算法在能源系统建模中的具体应用,重点关注状态设计、动作空间定义与奖励函数构造等关键环节,并可进一步扩展至多智能体强化学习或与其他优化算法的融合研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值