【BZOJ2809】【splay启发式合并】dispatching
2015-03-12 16:25
267 查看
Description
[align=left]在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。[/align][align=left]1 ≤N ≤ 100,000 忍者的个数;[/align]
[align=left]1 ≤M ≤ 1,000,000,000 薪水总预算; [/align]
[align=left] [/align]
[align=left]0 ≤Bi < i 忍者的上级的编号;[/align]
[align=left]1 ≤Ci ≤ M 忍者的薪水;[/align]
[align=left]1 ≤Li ≤ 1,000,000,000 忍者的领导力水平。[/align]
Input
[align=left]从标准输入读入数据。[/align][align=left] [/align]
[align=left]第一行包含两个整数 N和 M,其中 N表示忍者的个数,M表示薪水的总预算。[/align]
[align=left] [/align]
[align=left]接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整 Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力。Master满足B i = 0,并且每一个忍者的老板的编号一定小于自己的编号 Bi < i。[/align]
Output
[align=left]输出一个数,表示在预算内顾客的满意度的最大值。[/align][align=left] [/align]
[align=left] [/align]
Sample Input
5 40 3 3
1 3 5
2 2 2
1 2 4
2 3 1
Sample Output
6HINT
如果我们选择编号为 1的忍者作为管理者并且派遣第三个和第四个忍者,薪水总和为 4,没有超过总预算 4。因为派遣了 2 个忍者并且管理者的领导力为 3,用户的满意度为 2 ,是可以得到的用户满意度的最大值。
Source
【分析】什么启发式合并。叫得这么高端...不就是一个个插进去吗....
记得要用longlong
发现了一个很严重的问题,昨天的splay里面有问题。。
还是指针的问题....如果没有用引用的话就要返回,否则的话值不会变,貌似这个问题只有在以大小作为排序标准的情况下才会出现?
因为好像splay处理序列的时候一般是不需要根据大小排序的,所以一直没有发现....还好发现了,不然省选出现这个问题就跪了啊!!
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <utility> #include <iomanip> #include <string> #include <cmath> #include <queue> #include <assert.h> #include <map> #include <ctime> #include <cstdlib> #include <stack> #define LOCAL const int MAXN = 1020000 + 10; const int INF = 100000000; const int SIZE = 450; const int maxnode = 0x7fffffff + 10; using namespace std; vector<long long>G[MAXN]; stack<long long>S; long long n; long long b[MAXN]; long long c[MAXN], l[MAXN], m; struct SPLAY{ struct Node{ long long size; long long val, sum; Node *parent, *ch[2]; long long cmp(){ if (parent->ch[0] == this) return 0; else return 1; } }*nil, _nil, mem[MAXN], *root[MAXN]; long long tot, pos;//pos表示当前根是哪一个 void update(Node *&t){ if (t == nil) return; t->size = 1; t->size += t->ch[0]->size + t->ch[1]->size; t->sum = t->val; t->sum += t->ch[0]->sum + t->ch[1]->sum; return; } void init(){ //循环哨兵 nil = &_nil; _nil.val = _nil.size =_nil.sum = 0; _nil.parent = _nil.ch[0] = _nil.ch[1] = nil; tot = 0; //没有根就只能加一点特判断了 } Node *NEW(long long val){ Node *p = &mem[tot++]; p->size = 1; p->val = p->sum = val; p->parent = p->ch[0] = p->ch[1] = nil; return p; } //旋转,d代表1右旋 void Rotate(Node *t, long long d){ Node *p = t->parent; t = p->ch[d ^ 1]; p->ch[d ^ 1] = t->ch[d]; if (t->ch[d] != nil) t->ch[d]->parent = p; t->ch[d] = p; t->parent = p->parent; //注意不是引用 if (t->parent != nil){ if (t->parent->ch[0] == p) t->parent->ch[0] = t; else t->parent->ch[1] = t; } p->parent = t; if (t->parent == nil) root[pos] = t; update(p); update(t); } //没标记就是好TAT Node* splay(Node *x, Node *y){ while (x->parent != y){ if (x->parent->parent == y){ Rotate(x, x->cmp() ^ 1); break; }else{ Rotate(x->parent, x->parent->cmp() ^ 1); Rotate(x, x->cmp() ^ 1); } update(x); } update(x); return x; } void insert(Node *&t, long long val){ if (t == nil){ t = NEW(val); return; } Node *x = t; Node *y = t; while (1){ long long d = (val >= x->val); if (x->ch[d] == nil){ x->ch[d] = NEW(val); x->ch[d]->parent = x; //update(x); t = splay(x->ch[d], nil); return; }else {x = x->ch[d];} } return;//不用update } void push(Node *&t){ if ( t == nil) return; push(t->ch[1]); S.push(t->val); push(t->ch[0]); } //感动天地没有find! Node* merge(Node *a, Node *b, long long pa, long long pb){ if (a == nil) return b; else if (b == nil) return a; //注意是将b插入a,为了启发式合并要判断大小 if (a->size < b->size){ //swap(root[pa], root[pb]); swap(a, b); } push(b);//把p推到栈里面 while (!S.empty()){ insert(a, S.top()); S.pop(); } //delete b;//可以删掉吧.... return a; } //表示在Node*t中sum比m小 long long get(Node *t, long long val){ Node *x = t; long long cnt = 0; while (1){ if (x == nil) break; if (val >= x->sum) {cnt += x->size; break;}//一次性全部拿完,包括子树 //能往左走当然尽量往左 long long tmp = (x->ch[0]->sum); //拿完左子树去右边拿 if (val >= (tmp + x->val)) {cnt += x->ch[0]->size + 1; val -= tmp + x->val; x = x->ch[1];} else x = x->ch[0];//往左边拿 } return cnt; } void work(){ init(); while (!S.empty()) S.pop(); long long Ans = 0; for (long long i = n; i >= 1; i--){ if (G[i].size() == 0){//叶子节点 root[i] = NEW(c[i]); if (c[i] <= m) Ans = max(Ans, l[i]); continue; } if (i == 3){ //prlong long(root[8]); //printf("\n\n\n"); } root[i] = nil;//枚举每个管理者 pos = i; insert(root[i], c[i]); for (long long j = 0; j < G[i].size(); j++){ long long v = G[i][j]; root[i] = merge(root[i], root[G[i][j]], i, v); if (i == 3){ // prlong long(root[3]); //printf("\n\n\n"); } } //printf("%d\n", tot); //if ((get(root[i], m) * l[i]) == 12) //printf(""); if (i == 8){ //printf("%d", root[3]->size); //prlong long(root[8]); } Ans = max(Ans, get(root[i], m) * l[i]); } /*pos = n; insert(root , 10); insert(root , 1);*/ printf("%lld\n", Ans); //printf("%d", tot); } /*void print(Node *t){ if (t == nil) return ; prlong long(t->ch[0]); printf("%lld %lld\n", t->val, t->parent->val); prlong long(t->ch[1]); }*/ void debug(){ init(); Node *p = NEW(5); insert(p, 3); printf("%lld", p->val); } }A; void read(){ //memest long long sum = 0; scanf("%lld%lld", &n, &m);//m为薪水总预算 for (long long i = 1; i <= n; i++){ //分别代表上级薪水领导力 scanf("%lld%lld%lld", &b[i], &c[i], &l[i]); G[b[i]].push_back(i); //sum += c[i]; //printf("%d %lld %d\n", b[i], c[i], (2568 / 428)); } //第3个有6个 //printf("%d\n", m); } int main(){ read(); A.work(); //A.debug(); return 0; }
View Code
相关文章推荐
- 指令总预算BZOJ 2809([Apio2012]dispatching-Splay启发式合并)
- BZOJ 2809([Apio2012]dispatching-Splay启发式合并)
- BZOJ 2809 APIO2012 dispatching Treap+启发式合并 / 可并堆
- 2809: [Apio2012]dispatching|splay启发式合并
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
- BZOJ 2809 APIO 2012 dispatching 平衡树启发式合并
- bzoj 2733(splay启发式合并)
- [BZOJ3545][ONTAK2010]Peaks(splay启发式合并)
- BZOJ 3545: [ONTAK2010]Peaks [Splay启发式合并]
- bzoj 2733 [HNOI2012]永无乡 splay启发式合并
- BZOJ2809可合并堆或启发式合并
- bzoj 2733 永无乡 Splay 启发式合并
- BZOJ 3545: [ONTAK2010]Peaks|Splay启发式合并
- 【splay启发式合并】bzoj 2733 永无乡
- 【BZOJ 2733】【HNOI 2012】永无乡 Splay启发式合并
- BZOJ 2733: [HNOI2012]永无乡 [splay启发式合并]
- bzoj 2733 Splay 启发式合并,名次树
- BZOJ 2809 dispatching(splay 左偏树)
- 2809: [Apio2012]dispatching 启发式合并treap 可并堆
- 【BZOJ 2733】 [HNOI2012]永无乡|Splay启发式合并