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


    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("
    
    
    ");
    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("
    
    
    ");
    179                       }
    180                 }
    181                 //printf("%d
    ", 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
    ", 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
    ", 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
    ", b[i], c[i], (2568 / 428));
    221      }
    222      //第3个有6个 
    223      //printf("%d
    ", m);
    224 }
    225 
    226 int main(){
    227     
    228     read();
    229     A.work();
    230     //A.debug();
    231     return 0;
    232 }
    View Code
  • 相关阅读:
    前导问题word使用技巧解决Word 生成目录时前导符不一致的问题(即通常所谓的目录中省略号大小不一致)
    安装用户debian7安装oracle11g
    字节文件MP3格式音频文件结构解析
    Linux下硬盘分区的最佳方案
    802.1x客户端软件 2.4版破解支持多网卡
    z9jpz.dll、gq0aku0.exe、cms2cmw.sys病毒
    Ghost批处理文件的基本格式
    利用ASP远程注册DLL的方法
    dllhost.exe系统进程介绍
    Unicode 和多字节字符集 (MBCS)
  • 原文地址:https://www.cnblogs.com/hoskey/p/4332788.html
Copyright © 2020-2023  润新知