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

Description

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

 

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

Input

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

 

你可能感兴趣的:(Dispatch)