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 }